home *** CD-ROM | disk | FTP | other *** search
/ Action Games (2008) / akcnihry1.iso / AT-Robots 2.10 / ATR2.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-06-21  |  108.8 KB  |  3,614 lines

  1. {$G+}{$N+}{$E+}{$X+}{$D-}
  2. {$M 16384,0,655360}
  3. {                                                                           }
  4. {  AT-Robots 2,  Copyright 1997,'99, Ed T. Toton III, All Rights Reserved.  }
  5. {                                                                           }
  6. {    This Source code was not originally intended for general distribution. }
  7. { It is not optimized for anything in particular. It is not even intended   }
  8. { to be very clear or intelligible to anyone but myself. Nor is it designed }
  9. { to be portable. It is being distributed under a variant of the BSD        }
  10. { license (see below)                                                       }
  11. {                                                                           }
  12. { Designed for Turbo Pascal 6.0                                             }
  13. {                                                                           }
  14.  
  15. (* Code between {FIFI} and {/FIFI} tags were added by Fifi LaRoo. These
  16.    tags may eventually be removed (especially as they get modified in the
  17.    future), but are here for the time being to keep track of where the
  18.    changes were made.                                                      *)
  19.  
  20. (*
  21. Copyright (c) 1999, Ed T. Toton III. All rights reserved.
  22.  
  23. Redistribution and use in source and binary forms, with or without
  24. modification, are permitted provided that the following conditions
  25. are met:
  26.  
  27.    Redistributions of source code must retain the above copyright notice,
  28.    this list of conditions and the following disclaimer.
  29.  
  30.    Redistributions in binary form must reproduce the above copyright notice, 
  31.    this list of conditions and the following disclaimer in the documentation
  32.    and/or other materials provided with the distribution.
  33.  
  34.    All advertising materials mentioning features or use of this software
  35.    must display the following acknowledgement:
  36.  
  37.         This product includes software developed by Ed T. Toton III &
  38.         NecroBones Enterprises.
  39.  
  40.    No modified or derivative copies or software may be distributed in the
  41.    guise of official or original releases/versions of this software. Such
  42.    works must contain acknowledgement that it is modified from the original.
  43.  
  44.    Neither the name of the author nor the name of the business or
  45.    contributers may be used to endorse or promote products derived
  46.    from this software without specific prior written permission.
  47.  
  48. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 
  49. EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  50. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  51. DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
  52. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  53. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  54. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  55. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  56. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  57. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  58. *)
  59.  
  60.  
  61. Program Advanced_T_Robots_2;
  62.  
  63. uses dos, crt, graph, egavga, filelib, myfile, atr2func;
  64.  
  65. {Æß} {err}
  66.  
  67. const
  68.  progname       ='AT-Robots';
  69.  version        ='2.10';
  70.  cnotice1       ='Copyright 1997 ''99, Ed T. Toton III';
  71.  cnotice2       ='All Rights Reserved.';
  72.  main_filename  ='ATR2';
  73.  robot_ext      ='.AT2';
  74.  locked_ext     ='.ATL';
  75.  config_ext     ='.ATS';
  76.  compile_ext    ='.CMP';
  77.  report_ext     ='.REP';
  78.  
  79.  _T             =true;
  80.  _F             =false;
  81.  minint         =-32768; {maxint=32787 is alrady defined by turbo pascal}
  82.  
  83.  {debugging/compiler}
  84.  show_code      =_F;
  85.  compile_by_line=_F;
  86.  max_var_len    =16;
  87.  debugging_compiler=_F;
  88.  
  89.  {robots}
  90.  max_robots     =31;    {starts at 0, so total is max_robots+1}
  91.  max_code       =1023;  {same here}
  92.  max_op         =3;     {etc...}
  93.  max_stack      =256;   {but not here (it's a power of two, get the idea?)}
  94.  max_ram        =1023;  {but this does start at 0 (odd #, 2^n-1)}
  95.  max_vars       =256;
  96.  max_labels     =256;
  97.  acceleration   =4;
  98.  turn_rate      =8;
  99.  max_vel        =4;
  100.  max_missiles   =1023;
  101.  missile_spd    =32;
  102.  hit_range      =14;
  103.  blast_radius   =25;
  104.  crash_range    =8;
  105.  max_sonar      =250;
  106.  com_queue      =512;
  107.  max_queue      =255;
  108.  max_config_points=12;
  109.  max_mines      =63;
  110.  mine_blast     =35;
  111.  
  112.  {simulator & graphics}
  113.  screen_scale   =0.46;
  114.  screen_x       =5;
  115.  screen_y       =5;
  116.  robot_scale    =06;
  117.  default_delay  =20;
  118.  default_slice  =05;
  119.  mine_circle    =trunc(mine_blast*screen_scale)+1;
  120.  blast_circle   =trunc(blast_radius*screen_scale)+1;
  121.  mis_radius     =trunc(hit_range/2)+1;
  122.  max_robot_lines=8;
  123.  Gray50 : FillPatternType = ($AA, $55, $AA, $55,
  124.                              $AA, $55, $AA, $55);
  125.  
  126.  
  127. type
  128.  op_rec         = record
  129.                    op:array[0..max_op] of integer;
  130.                   end;
  131.  prog_type      = array[0..max_code] of op_rec;
  132.  config_rec     = record
  133.                    scanner,weapon,armor,engine,heatsinks,shield,mines:integer;
  134.                   end;
  135.  mine_rec       = record
  136.                    x,y:real;
  137.                    detect,yield:integer;
  138.                    detonate:boolean;
  139.                   end;
  140.  robot_rec      = record
  141.                    {FIFI}
  142.                    is_locked:boolean;  {used to determine wether to allow debugger}
  143.                    mem_watch:integer;  {current base of memory view for debugger}
  144.                    {/FIFI}
  145.                    x,y,lx,ly,xv,yv,speed,shotstrength,damageadj,speedadj,meters:real;
  146.                    hd,thd,lhd,spd,tspd,armor,larmor,heat,lheat,ip,
  147.                    plen,scanarc,accuracy,shift,err,delay_left,robot_time_limit,
  148.                    max_time,time_left,lshift,arc_count,sonar_count,scanrange,
  149.                    last_damage,last_hit,transponder,shutdown,channel,
  150.                    lendarc,endarc,lstartarc,startarc,mines:integer;
  151.                    tx,ltx,ty,lty:array[1..max_robot_lines] of integer;
  152.                    wins,trials,kills,deaths,startkills,shots_fired,match_shots,
  153.                    hits,damage_total,cycles_lived,error_count:longint;
  154.                    config:config_rec;
  155.                    name:string[31];
  156.                    fn:string[255];
  157.                    shields_up,lshields,overburn,keepshift,cooling,won:boolean;
  158.                    code:prog_type;
  159.                    stack:array[1..max_stack] of integer;
  160.                    ram:array[0..max_ram] of integer;
  161.                    mine:array[0..max_mines] of mine_rec;
  162.                    errorlog:text;
  163.                   end;
  164.  parsetype      = array[0..max_op] of string[16];
  165.  robot_ptr      = ^robot_rec;
  166.  missile_rec    = record
  167.                    x,y,lx,ly,mult,mspd:real;
  168.                    source,a,hd,rad,lrad,max_rad:integer;
  169.                   end;
  170.  
  171. var
  172.  
  173.  {--robot variables--}
  174.  num_robots:integer;
  175.  robot:array[-2..max_robots+2] of robot_ptr; { a few extra pointers for luck.. :) }
  176.  missile:array[0..max_missiles] of missile_rec;
  177.  
  178.  {--compiler variables--}
  179.  f:text;
  180.  numvars,numlabels,maxcode,lock_pos,lock_dat:integer;
  181.  varname:array[1..max_vars] of string[max_var_len];
  182.  varloc:array[1..max_vars] of integer;
  183.  labelname:array[1..max_vars] of string[max_var_len];
  184.  labelnum:array[1..max_labels] of integer;
  185.  show_source,compile_only:boolean;
  186.  lock_code:string;
  187.  
  188.  {--simulator/graphics variables--}
  189.  {FIFI}
  190.  bout_over:boolean;     {made global from procedure bout}
  191.  step_mode:integer;     {0=off, for (0<step_mode<=9) = #of game cycles per step}
  192.  temp_mode:integer;     {stores previous step_mode for return to step}
  193.  step_count:integer;    {step counter used as break flag}
  194.  step_loop:boolean;     {break flag for stepping}
  195.  {show_debugger:boolean;} {flag for viewing debugger panel vs. robot stats}
  196.  {/FIFI}
  197.  old_shields,insane_missiles,debug_info,windoze,no_gfx,
  198.  logging_errors,timing,show_arcs:boolean;
  199.  game_delay,time_slice,insanity,update_timer,max_gx,max_gy,stats_mode:integer;
  200.  game_limit,game_cycle:longint;
  201.  matches,played,executed:longint;
  202.  
  203.  {--general settings--}
  204.  quit,report,show_cnotice:boolean;
  205.  kill_count,report_type:integer;
  206.  
  207.  
  208.  
  209. function operand(n,m:integer):string;
  210. var
  211.  s:string;
  212. begin
  213.  s:=cstr(n);
  214.      (*
  215.      Microcode:
  216.         0 = instruction, number, constant
  217.         1 = variable, memory access
  218.         2 = :label
  219.         3 = !label (unresolved)
  220.         4 = !label (resolved)
  221.        8h mask = inderect addressing (enclosed in [])
  222.      *)
  223.  case m and 7 of
  224.   1:s:='@'+s;
  225.   2:s:=':'+s;
  226.   3:s:='$'+s;
  227.   4:s:='!'+s;
  228.   else s:=cstr(n);
  229.  end;
  230.  if m and 8>0 then s:='['+s+']';
  231.  operand:=s;
  232. end;
  233.  
  234. function mnemonic(n,m:integer):string;
  235. var
  236. s:string;
  237. begin
  238.  s:=cstr(n);
  239.  if m=0 then
  240.   case n of
  241.    00:s:='NOP';
  242.    01:s:='ADD';
  243.    02:s:='SUB';
  244.    03:s:='OR';
  245.    04:s:='AND';
  246.    05:s:='XOR';
  247.    06:s:='NOT';
  248.    07:s:='MPY';
  249.    08:s:='DIV';
  250.    09:s:='MOD';
  251.    10:s:='RET';
  252.    11:s:='CALL';
  253.    12:s:='JMP';
  254.    13:s:='JLS';
  255.    14:s:='JGR';
  256.    15:s:='JNE';
  257.    16:s:='JE';
  258.    17:s:='SWAP';
  259.    18:s:='DO';
  260.    19:s:='LOOP';
  261.    20:s:='CMP';
  262.    21:s:='TEST';
  263.    22:s:='MOV';
  264.    23:s:='LOC';
  265.    24:s:='GET';
  266.    25:s:='PUT';
  267.    26:s:='INT';
  268.    27:s:='IPO';
  269.    28:s:='OPO';
  270.    29:s:='DELAY';
  271.    30:s:='PUSH';
  272.    31:s:='POP';
  273.    32:s:='ERR';
  274.    33:s:='INC';
  275.    34:s:='DEC';
  276.    35:s:='SHL';
  277.    36:s:='SHR';
  278.    37:s:='ROL';
  279.    38:s:='ROR';
  280.    39:s:='JZ';
  281.    40:s:='JNZ';
  282.    41:s:='JGE';
  283.    42:s:='JLE';
  284.    43:s:='SAL';
  285.    44:s:='SAR';
  286.    45:s:='NEG';
  287.    46:s:='JTL';
  288.    else s:='XXX';
  289.   end else s:=operand(n,m);
  290.  mnemonic:=s;
  291. end;
  292.  
  293. procedure log_error(n,i:integer;ov:string);
  294. var
  295.  j,k:integer;
  296.  s:string;
  297. begin
  298.  if not logging_errors then exit;
  299.  with robot[n]^ do
  300.   begin
  301.    case i of
  302.     01:s:='Stack full - Too many CALLs?';
  303.     02:s:='Label not found. Hmmm.';
  304.     03:s:='Can''t assign value - Tisk tisk.';
  305.     04:s:='Illegal memory reference';
  306.     05:s:='Stack empty - Too many RETs?';
  307.     06:s:='Illegal instruction. How bizarre.';
  308.     07:s:='Return out of range - Woops!';
  309.     08:s:='Divide by zero';
  310.     09:s:='Unresolved !label. WTF?';
  311.     10:s:='Invalid Interrupt Call';
  312.     11:s:='Invalid Port Access';
  313.     12:s:='Com Queue empty';
  314.     13:s:='No mine-layer, silly.';
  315.     14:s:='No mines left';
  316.     15:s:='No shield installed - Arm the photon torpedoes instead. :-)';
  317.     16:s:='Invalid Microcode in instruction.';
  318.     else s:='Unkown error';
  319.    end;
  320.    writeln(errorlog,'<',i,'> ',s,' (Line #',ip,') [Cycle: ',game_cycle,', Match: ',played,'/',matches,']');
  321.    write(errorlog,' ',mnemonic(code[ip].op[0],code[ip].op[3] and 15),'  ',
  322.                       operand(code[ip].op[1],(code[ip].op[3] shr 4) and 15),', ',
  323.                       operand(code[ip].op[2],(code[ip].op[3] shr 8) and 15));
  324.    if ov<>'' then writeln(errorlog,'    (Values: ',ov,')')
  325.              else writeln(errorlog);
  326.    write(errorlog,' AX=',addrear(cstr(ram[65])+',',7));
  327.    write(errorlog,' BX=',addrear(cstr(ram[66])+',',7));
  328.    write(errorlog,' CX=',addrear(cstr(ram[67])+',',7));
  329.    write(errorlog,' DX=',addrear(cstr(ram[68])+',',7));
  330.    write(errorlog,' EX=',addrear(cstr(ram[69])+',',7));
  331.    write(errorlog,' FX=',addrear(cstr(ram[70])+',',7));
  332.    writeln(errorlog,' Flags=',ram[64]);
  333.    write(errorlog,' AX=',addrear(hex(ram[65])+',',7));
  334.    write(errorlog,' BX=',addrear(hex(ram[66])+',',7));
  335.    write(errorlog,' CX=',addrear(hex(ram[67])+',',7));
  336.    write(errorlog,' DX=',addrear(hex(ram[68])+',',7));
  337.    write(errorlog,' EX=',addrear(hex(ram[69])+',',7));
  338.    write(errorlog,' FX=',addrear(hex(ram[70])+',',7));
  339.    writeln(errorlog,' Flags=',hex(ram[64]));
  340.    writeln(errorlog);
  341.   end;
  342. end;
  343.  
  344. function max_shown:integer;
  345. begin
  346.  case stats_mode of
  347.   1:max_shown:=12;
  348.   2:max_shown:=32;
  349.   else max_shown:=6;
  350.  end;
  351. end;
  352.  
  353. function graph_check(n:integer):boolean;
  354. var
  355.  ok:boolean;
  356. begin
  357.  ok:=true;
  358.  if (not graphix) or (n<0) or (n>num_robots) or (n>=max_shown) then ok:=false;
  359.  graph_check:=ok;
  360. end;
  361.  
  362. procedure robot_graph(n:integer);
  363. begin
  364.  case stats_mode of
  365.   1:begin viewport(480,4+n*35,635,37+n*35); max_gx:=155; max_gy:=33; end;
  366.   2:begin viewport(480,4+n*13,635,15+n*13); max_gx:=155; max_gy:=11; end;
  367.   else begin viewport(480,4+n*70,635,70+n*70); max_gx:=155; max_gy:=66; end;
  368.  end;
  369.  setfillstyle(1,robot_color(n));
  370.  setcolor(robot_color(n));
  371. end;
  372.  
  373. procedure update_armor(n:integer);
  374. begin
  375.  if graph_check(n) {FIFI} and (step_mode<=0) {/FIFI} then
  376.  with robot[n]^ do
  377.   begin
  378.    robot_graph(n);
  379.    if armor>0 then
  380.     case stats_mode of
  381.      1:bar(30,13,29+armor,18);
  382.      2:bar(88,03,87+(armor shr 2),08);
  383.      else bar(30,25,29+armor,30);
  384.     end;
  385.    setfillstyle(1,8);
  386.    if armor<100 then
  387.     case stats_mode of
  388.      1:bar(30+armor,13,129,18);
  389.      2:bar(88+(armor shr 2),03,111,08);
  390.      else bar(30+armor,25,129,30);
  391.     end;
  392.   end;
  393. end;
  394.  
  395. procedure update_heat(n:integer);
  396. begin
  397.  if graph_check(n) {FIFI} and (step_mode<=0) {/FIFI} then
  398.  with robot[n]^ do
  399.   begin
  400.    robot_graph(n);
  401.    if heat>5 then
  402.     case stats_mode of
  403.      1:bar(030,23,029+(heat div 5),28);
  404.      2:bar(127,03,126+(heat div 20),08);
  405.      else bar(30,35,29+(heat div 5),40);
  406.     end;
  407.    setfillstyle(1,8);
  408.    if heat<500 then
  409.     case stats_mode of
  410.      1:bar(030+(heat div 5),23,129,28);
  411.      2:bar(127+(heat div 20),03,151,08);
  412.      else bar(30+(heat div 5),35,129,40);
  413.     end;
  414.   end;
  415. end;
  416.  
  417. procedure robot_error(n,i:integer;ov:string);
  418. begin
  419.  if graph_check(n) {FIFI} and (step_mode<=0) {/FIFI} then
  420.  with robot[n]^ do
  421.   begin
  422.    if (stats_mode=0) then
  423.     begin
  424.      robot_graph(n);
  425.      setfillstyle(1,0);
  426.      bar(66,56,154,64);
  427.      setcolor(robot_color(n));
  428.      outtextxy(66,56,addrear(cstr(i),7)+hex(i));
  429.      chirp;
  430.     end;
  431.    if logging_errors then log_error(n,i,ov);
  432.    inc(error_count);
  433.   end;
  434. end;
  435.  
  436. procedure update_lives(n:integer);
  437. begin
  438.  if graph_check(n) and (stats_mode=0) {FIFI} and (step_mode<=0) {/FIFI} then
  439.  with robot[n]^ do
  440.   begin
  441.    robot_graph(n);
  442.    setcolor(robot_color(n)-8);
  443.    setfillstyle(1,0);
  444.    bar(011,46,130,53);
  445.    outtextxy(011,46,'K:');
  446.    outtextxy(029,46,zero_pad(kills,4));
  447.    outtextxy(080,46,'D:');
  448.    outtextxy(098,46,zero_pad(deaths,4));
  449.   end;
  450. end;
  451.  
  452. procedure update_cycle_window;
  453. begin
  454.  if not graphix then
  455.   begin
  456.    write(#13+'Match ',played,'/',matches,', Cycle: ',zero_pad(game_cycle,9));
  457.   end
  458.  else
  459.   begin
  460.    viewport(480,440,635,475);
  461.    setfillstyle(1,0);
  462.    bar(59,2,154,10);
  463.    setcolor(7);
  464.    outtextxy(75,03,zero_pad(game_cycle,9));
  465.   end;
  466. end;
  467.  
  468. procedure setscreen;
  469. var
  470.  i:integer;
  471. begin
  472.  if not graphix then exit;
  473.  viewport(0,0,639,479);
  474.  box(0,0,639,479);
  475.  
  476.  stats_mode:=0;
  477.  case num_robots of
  478.   0..5:stats_mode:=0;
  479.   6..11:stats_mode:=1;
  480.   12..max_robots:stats_mode:=2;
  481.   else stats_mode:=0;
  482.  end;
  483.  
  484.  {--main arena--}
  485.  hole(4,4,475,475);
  486.  
  487.  {--cycle window--}
  488.  viewport(480,430,635,475);
  489.  hole(0,0,155,45);
  490.  setcolor(7);
  491.  outtextxy(3,03,'FreeMem: '+cstr(memavail));
  492.  outtextxy(3,13,'Cycle:   ');
  493.  outtextxy(3,23,'Limit:   '+zero_pad(game_limit,9));
  494.  outtextxy(3,33,'Match:   '+cstr(played)+'/'+cstr(matches));
  495.  update_cycle_window;
  496.  
  497.  {--robot windows--}
  498.  for i:=0 to max_robots do
  499.   if i<max_shown then with robot[i]^ do
  500.    begin
  501.     robot_graph(i);
  502.     hole(0,0,max_gx,max_gy);
  503.     if i<=num_robots then
  504.      begin
  505.       setcolor(robot_color(i));
  506.       outtextxy(003,02,base_name(no_path(fn)));
  507.       case stats_mode of
  508.        1:begin
  509.           outtextxy(003,12,' A:');
  510.           outtextxy(003,22,' H:');
  511.          end;
  512.        2:begin
  513.           setcolor(robot_color(i) and 7);
  514.           outtextxy(080,02,'A');
  515.           outtextxy(118,02,'H');
  516.          end;
  517.        else begin
  518.           outtextxy(003,24,' A:');
  519.           outtextxy(003,34,' H:');
  520.          end;
  521.       end;
  522.       setcolor(robot_color(i));
  523.       if stats_mode<=1 then
  524.        begin
  525.         outtextxy(080,02,'Wins:');
  526.         outtextxy(122,02,zero_pad(wins,4));
  527.        end;
  528.       if stats_mode=0 then
  529.        begin
  530.         outtextxy(003,56,' Error:');
  531.         setcolor(robot_color(i) and 7);
  532.         outtextxy(003,12,name);
  533.         setcolor(8);
  534.         outtextxy(66,56,'None');
  535.        end;
  536.       lx:=1000-x; ly:=1000-y;
  537.       update_armor(i);
  538.       update_heat(i);
  539.       update_lives(i);
  540.      end
  541.     else
  542.      begin
  543.       setfillpattern(gray50,8);
  544.       bar(1,1,max_gx-1,max_gy-1);
  545.      end;
  546.    end;
  547. end;
  548.  
  549. procedure graph_mode(on:boolean);
  550. begin
  551.  if on and (not graphix) then
  552.   begin
  553.    Graph_VGA;
  554.    cleardevice;
  555.    setscreen;
  556.    graphix:=true;
  557.   end
  558.  else
  559.   if (not on) and graphix then
  560.    begin
  561.     closegraph;
  562.     graphix:=false;
  563.    end;
  564. end;
  565.  
  566. procedure prog_error(n:integer; ss:string);
  567. var
  568.  s:string;
  569. begin
  570.  graph_mode(false);
  571.  textcolor(15);
  572.  write('Error #',n,': ');
  573.  case n of
  574.   00:s:=ss;(*user error*)
  575.   01:s:='Invalid :label - "'+ss+'", silly mortal.';
  576.   02:s:='Undefined identifier - "'+ss+'". A typo perhaps?';
  577.   03:s:='Memory access out of range - "'+ss+'"';
  578.   04:s:='Not enough robots for combat. Maybe we should just drive in circles.';
  579.   05:s:='Robot names and settings must be specified. An empty arena is no fun.';
  580.   06:s:='Config file not found - "'+ss+'"';
  581.   07:s:='Cannot access a config file from a config file - "'+ss+'"';
  582.   08:s:='Robot not found "'+ss+'". Perhaps you mistyped it?';
  583.   09:s:='Insufficient RAM to load robot: "'+ss+'"... This is not good.';
  584.   10:s:='Too many robots! We can only handle '+cstr(max_robots+1)+'! Blah.. limits are limits.';
  585.   11:s:='You already have a perfectly good #def for "'+ss+'", silly.';
  586.   12:s:='Variable name too long! (Max:'+cstr(max_var_len)+') "'+ss+'"';
  587.   13:s:='!Label already defined "'+ss+'", silly.';
  588.   14:s:='Too many variables! (Var Limit: '+cstr(max_vars)+')';
  589.   15:s:='Too many !labels! (!Label Limit: '+cstr(max_labels)+')';
  590.   16:s:='Robot program too long! Boldly we simplify, simplify along...'+ss;
  591.   17:s:='!Label missing error. !Label #'+ss+'.';
  592.   18:s:='!Label out of range: '+ss;
  593.   19:s:='!Label not found. '+ss;
  594.   20:s:='Invalid config option: "'+ss+'". Inventing a new device?';
  595.   21:s:='Robot is attempting to cheat; Too many config points ('+ss+')';
  596.   22:s:='Insufficient data in data statement: "'+ss+'"';
  597.   23:s:='Too many asterisks: "'+ss+'"';
  598.   {FIFI}
  599.   24:s:='Invalid step count: "'+ss+'". 1-9 are valid conditions.';
  600.   {/FIFI}
  601.   25:s:='"'+ss+'"';
  602.   else s:=ss;
  603.  end;
  604.  writeln(s);
  605.  writeln;
  606.  halt;
  607. end;
  608.  
  609. procedure print_code(n,p:integer);
  610. var
  611.  i:integer;
  612. begin
  613.   begin
  614.    write(hex(p)+': ');
  615.    for i:=0 to max_op do
  616.     write(zero_pad(robot[n]^.code[p].op[i],5),' ');
  617.    write(' =  ');
  618.    for i:=0 to max_op do
  619.     write(hex(robot[n]^.code[p].op[i]),'h ');
  620.    writeln; writeln;
  621.   end;
  622. end;
  623.  
  624. procedure parse1(n,p:integer; s:parsetype);
  625. var
  626.  i,j,k,opcode,microcode:integer;
  627.  found,indirect:boolean;
  628.  ss:string;
  629. begin
  630.  with robot[n]^ do
  631.   begin
  632.    for i:=0 to max_op-1 do
  633.     begin
  634.      k:=0; found:=false;
  635.      opcode:=0;    {nop}
  636.      microcode:=0; {instruction/constant}
  637.      s[i]:=btrim(ucase(s[i]));
  638.      indirect:=false;
  639.  
  640.      (*
  641.      Microcode:
  642.         0 = instruction, number, constant
  643.         1 = variable, memory access
  644.         2 = :label
  645.         3 = !label (unresolved)
  646.         4 = !label (resolved)
  647.        8h mask = inderect addressing (enclosed in [])
  648.      *)
  649.  
  650.      if s[i]='' then begin opcode:=0; microcode:=0; found:=true; end;
  651.  
  652.      if (lstr(s[i],1)='[') and (rstr(s[i],1)=']') then
  653.        begin
  654.         s[i]:=copy(s[i],2,length(s[i])-2);
  655.         indirect:=true;
  656.        end;
  657.  
  658.      {!labels}
  659.      if (not found) and (s[i][1]='!') then
  660.       begin
  661.        ss:=s[i];
  662.        ss:=btrim(rstr(ss,length(ss)-1));
  663.        if numlabels>0 then
  664.         for j:=1 to numlabels do
  665.          if ss=labelname[j] then
  666.           begin
  667.            found:=true;
  668.            if labelnum[j]>=0 then
  669.              begin opcode:=labelnum[j]; microcode:=4; {resolved !label} end
  670.             else
  671.              begin opcode:=j; microcode:=3; {unresolved !label} end;
  672.           end;
  673.        if not found then
  674.         begin
  675.          inc(numlabels);
  676.          if numlabels>max_labels then prog_error(15,'')
  677.           else
  678.            begin
  679.             labelname[numlabels]:=ss;
  680.             labelnum[numlabels]:=-1;
  681.             opcode:=numlabels;
  682.             microcode:=3; {unresolved !label}
  683.             found:=true;
  684.            end;
  685.         end;
  686.       end;
  687.  
  688.      {variables}
  689.      if (numvars>0) and (not found) then
  690.       for j:=1 to numvars do
  691.        if s[i]=varname[j] then
  692.         begin
  693.          opcode:=varloc[j];
  694.          microcode:=1; {variable}
  695.          found:=true;
  696.         end;
  697.  
  698.      {instructions}
  699.      if s[i]='NOP'     then begin opcode:=000; found:=true; end;
  700.      if s[i]='ADD'     then begin opcode:=001; found:=true; end;
  701.      if s[i]='SUB'     then begin opcode:=002; found:=true; end;
  702.      if s[i]='OR'      then begin opcode:=003; found:=true; end;
  703.      if s[i]='AND'     then begin opcode:=004; found:=true; end;
  704.      if s[i]='XOR'     then begin opcode:=005; found:=true; end;
  705.      if s[i]='NOT'     then begin opcode:=006; found:=true; end;
  706.      if s[i]='MPY'     then begin opcode:=007; found:=true; end;
  707.      if s[i]='DIV'     then begin opcode:=008; found:=true; end;
  708.      if s[i]='MOD'     then begin opcode:=009; found:=true; end;
  709.      if s[i]='RET'     then begin opcode:=010; found:=true; end;
  710.      if s[i]='RETURN'  then begin opcode:=010; found:=true; end;
  711.      if s[i]='GSB'     then begin opcode:=011; found:=true; end;
  712.      if s[i]='GOSUB'   then begin opcode:=011; found:=true; end;
  713.      if s[i]='CALL'    then begin opcode:=011; found:=true; end;
  714.      if s[i]='JMP'     then begin opcode:=012; found:=true; end;
  715.      if s[i]='JUMP'    then begin opcode:=012; found:=true; end;
  716.      if s[i]='GOTO'    then begin opcode:=012; found:=true; end;
  717.      if s[i]='JLS'     then begin opcode:=013; found:=true; end;
  718.      if s[i]='JB'      then begin opcode:=013; found:=true; end;
  719.      if s[i]='JGR'     then begin opcode:=014; found:=true; end;
  720.      if s[i]='JA'      then begin opcode:=014; found:=true; end;
  721.      if s[i]='JNE'     then begin opcode:=015; found:=true; end;
  722.      if s[i]='JEQ'     then begin opcode:=016; found:=true; end;
  723.      if s[i]='JE'      then begin opcode:=016; found:=true; end;
  724.      if s[i]='XCHG'    then begin opcode:=017; found:=true; end;
  725.      if s[i]='SWAP'    then begin opcode:=017; found:=true; end;
  726.      if s[i]='DO'      then begin opcode:=018; found:=true; end;
  727.      if s[i]='LOOP'    then begin opcode:=019; found:=true; end;
  728.      if s[i]='CMP'     then begin opcode:=020; found:=true; end;
  729.      if s[i]='TEST'    then begin opcode:=021; found:=true; end;
  730.      if s[i]='SET'     then begin opcode:=022; found:=true; end;
  731.      if s[i]='MOV'     then begin opcode:=022; found:=true; end;
  732.      if s[i]='LOC'     then begin opcode:=023; found:=true; end;
  733.      if s[i]='ADDR'    then begin opcode:=023; found:=true; end;
  734.      if s[i]='GET'     then begin opcode:=024; found:=true; end;
  735.      if s[i]='PUT'     then begin opcode:=025; found:=true; end;
  736.      if s[i]='INT'     then begin opcode:=026; found:=true; end;
  737.      if s[i]='IPO'     then begin opcode:=027; found:=true; end;
  738.      if s[i]='IN'      then begin opcode:=027; found:=true; end;
  739.      if s[i]='OPO'     then begin opcode:=028; found:=true; end;
  740.      if s[i]='OUT'     then begin opcode:=028; found:=true; end;
  741.      if s[i]='DEL'     then begin opcode:=029; found:=true; end;
  742.      if s[i]='DELAY'   then begin opcode:=029; found:=true; end;
  743.      if s[i]='PUSH'    then begin opcode:=030; found:=true; end;
  744.      if s[i]='POP'     then begin opcode:=031; found:=true; end;
  745.      if s[i]='ERR'     then begin opcode:=032; found:=true; end;
  746.      if s[i]='ERROR'   then begin opcode:=032; found:=true; end;
  747.      if s[i]='INC'     then begin opcode:=033; found:=true; end;
  748.      if s[i]='DEC'     then begin opcode:=034; found:=true; end;
  749.      if s[i]='SHL'     then begin opcode:=035; found:=true; end;
  750.      if s[i]='SHR'     then begin opcode:=036; found:=true; end;
  751.      if s[i]='ROL'     then begin opcode:=037; found:=true; end;
  752.      if s[i]='ROR'     then begin opcode:=038; found:=true; end;
  753.      if s[i]='JZ'      then begin opcode:=039; found:=true; end;
  754.      if s[i]='JNZ'     then begin opcode:=040; found:=true; end;
  755.      if s[i]='JAE'     then begin opcode:=041; found:=true; end;
  756.      if s[i]='JGE'     then begin opcode:=041; found:=true; end;
  757.      if s[i]='JLE'     then begin opcode:=042; found:=true; end;
  758.      if s[i]='JBE'     then begin opcode:=042; found:=true; end;
  759.      if s[i]='SAL'     then begin opcode:=043; found:=true; end;
  760.      if s[i]='SAR'     then begin opcode:=044; found:=true; end;
  761.      if s[i]='NEG'     then begin opcode:=045; found:=true; end;
  762.      if s[i]='JTL'     then begin opcode:=046; found:=true; end;
  763.  
  764.      {registers}
  765.      if s[i]='COLCNT'  then begin opcode:=008; microcode:=01; found:=true; end;
  766.      if s[i]='METERS'  then begin opcode:=009; microcode:=01; found:=true; end;
  767.      if s[i]='COMBASE' then begin opcode:=010; microcode:=01; found:=true; end;
  768.      if s[i]='COMEND'  then begin opcode:=011; microcode:=01; found:=true; end;
  769.      if s[i]='FLAGS'   then begin opcode:=064; microcode:=01; found:=true; end;
  770.      if s[i]='AX'      then begin opcode:=065; microcode:=01; found:=true; end;
  771.      if s[i]='BX'      then begin opcode:=066; microcode:=01; found:=true; end;
  772.      if s[i]='CX'      then begin opcode:=067; microcode:=01; found:=true; end;
  773.      if s[i]='DX'      then begin opcode:=068; microcode:=01; found:=true; end;
  774.      if s[i]='EX'      then begin opcode:=069; microcode:=01; found:=true; end;
  775.      if s[i]='FX'      then begin opcode:=070; microcode:=01; found:=true; end;
  776.      if s[i]='SP'      then begin opcode:=071; microcode:=01; found:=true; end;
  777.  
  778.      {constants}
  779.      if s[i]='MAXINT'    then begin opcode:=32767;  microcode:=0; found:=true; end;
  780.      if s[i]='MININT'    then begin opcode:=-32768; microcode:=0; found:=true; end;
  781.      if s[i]='P_SPEDOMETER'  then begin opcode:=01; microcode:=0; found:=true; end;
  782.      if s[i]='P_HEAT'        then begin opcode:=02; microcode:=0; found:=true; end;
  783.      if s[i]='P_COMPASS'     then begin opcode:=03; microcode:=0; found:=true; end;
  784.      if s[i]='P_TANGLE'      then begin opcode:=04; microcode:=0; found:=true; end;
  785.      if s[i]='P_TURRET_OFS'  then begin opcode:=04; microcode:=0; found:=true; end;
  786.      if s[i]='P_THEADING'    then begin opcode:=05; microcode:=0; found:=true; end;
  787.      if s[i]='P_TURRET_ABS'  then begin opcode:=05; microcode:=0; found:=true; end;
  788.      if s[i]='P_ARMOR'       then begin opcode:=06; microcode:=0; found:=true; end;
  789.      if s[i]='P_DAMAGE'      then begin opcode:=06; microcode:=0; found:=true; end;
  790.      if s[i]='P_SCAN'        then begin opcode:=07; microcode:=0; found:=true; end;
  791.      if s[i]='P_ACCURACY'    then begin opcode:=08; microcode:=0; found:=true; end;
  792.      if s[i]='P_RADAR'       then begin opcode:=09; microcode:=0; found:=true; end;
  793.      if s[i]='P_RANDOM'      then begin opcode:=10; microcode:=0; found:=true; end;
  794.      if s[i]='P_RAND'        then begin opcode:=10; microcode:=0; found:=true; end;
  795.      if s[i]='P_THROTTLE'    then begin opcode:=11; microcode:=0; found:=true; end;
  796.      if s[i]='P_TROTATE'     then begin opcode:=12; microcode:=0; found:=true; end;
  797.      if s[i]='P_OFS_TURRET'  then begin opcode:=12; microcode:=0; found:=true; end;
  798.      if s[i]='P_TAIM'        then begin opcode:=13; microcode:=0; found:=true; end;
  799.      if s[i]='P_ABS_TURRET'  then begin opcode:=13; microcode:=0; found:=true; end;
  800.      if s[i]='P_STEERING'    then begin opcode:=14; microcode:=0; found:=true; end;
  801.      if s[i]='P_WEAP'        then begin opcode:=15; microcode:=0; found:=true; end;
  802.      if s[i]='P_WEAPON'      then begin opcode:=15; microcode:=0; found:=true; end;
  803.      if s[i]='P_FIRE'        then begin opcode:=15; microcode:=0; found:=true; end;
  804.      if s[i]='P_SONAR'       then begin opcode:=16; microcode:=0; found:=true; end;
  805.      if s[i]='P_ARC'         then begin opcode:=17; microcode:=0; found:=true; end;
  806.      if s[i]='P_SCANARC'     then begin opcode:=17; microcode:=0; found:=true; end;
  807.      if s[i]='P_OVERBURN'    then begin opcode:=18; microcode:=0; found:=true; end;
  808.      if s[i]='P_TRANSPONDER' then begin opcode:=19; microcode:=0; found:=true; end;
  809.      if s[i]='P_SHUTDOWN'    then begin opcode:=20; microcode:=0; found:=true; end;
  810.      if s[i]='P_CHANNEL'     then begin opcode:=21; microcode:=0; found:=true; end;
  811.      if s[i]='P_MINELAYER'   then begin opcode:=22; microcode:=0; found:=true; end;
  812.      if s[i]='P_MINETRIGGER' then begin opcode:=23; microcode:=0; found:=true; end;
  813.      if s[i]='P_SHIELD'      then begin opcode:=24; microcode:=0; found:=true; end;
  814.      if s[i]='P_SHIELDS'     then begin opcode:=24; microcode:=0; found:=true; end;
  815.      if s[i]='I_DESTRUCT'    then begin opcode:=00; microcode:=0; found:=true; end;
  816.      if s[i]='I_RESET'       then begin opcode:=01; microcode:=0; found:=true; end;
  817.      if s[i]='I_LOCATE'      then begin opcode:=02; microcode:=0; found:=true; end;
  818.      if s[i]='I_KEEPSHIFT'   then begin opcode:=03; microcode:=0; found:=true; end;
  819.      if s[i]='I_OVERBURN'    then begin opcode:=04; microcode:=0; found:=true; end;
  820.      if s[i]='I_ID'          then begin opcode:=05; microcode:=0; found:=true; end;
  821.      if s[i]='I_TIMER'       then begin opcode:=06; microcode:=0; found:=true; end;
  822.      if s[i]='I_ANGLE'       then begin opcode:=07; microcode:=0; found:=true; end;
  823.      if s[i]='I_TID'         then begin opcode:=08; microcode:=0; found:=true; end;
  824.      if s[i]='I_TARGETID'    then begin opcode:=08; microcode:=0; found:=true; end;
  825.      if s[i]='I_TINFO'       then begin opcode:=09; microcode:=0; found:=true; end;
  826.      if s[i]='I_TARGETINFO'  then begin opcode:=09; microcode:=0; found:=true; end;
  827.      if s[i]='I_GINFO'       then begin opcode:=10; microcode:=0; found:=true; end;
  828.      if s[i]='I_GAMEINFO'    then begin opcode:=10; microcode:=0; found:=true; end;
  829.      if s[i]='I_RINFO'       then begin opcode:=11; microcode:=0; found:=true; end;
  830.      if s[i]='I_ROBOTINFO'   then begin opcode:=11; microcode:=0; found:=true; end;
  831.      if s[i]='I_COLLISIONS'  then begin opcode:=12; microcode:=0; found:=true; end;
  832.      if s[i]='I_RESETCOLCNT' then begin opcode:=13; microcode:=0; found:=true; end;
  833.      if s[i]='I_TRANSMIT'    then begin opcode:=14; microcode:=0; found:=true; end;
  834.      if s[i]='I_RECEIVE'     then begin opcode:=15; microcode:=0; found:=true; end;
  835.      if s[i]='I_DATAREADY'   then begin opcode:=16; microcode:=0; found:=true; end;
  836.      if s[i]='I_CLEARCOM'    then begin opcode:=17; microcode:=0; found:=true; end;
  837.      if s[i]='I_KILLS'       then begin opcode:=18; microcode:=0; found:=true; end;
  838.      if s[i]='I_DEATHS'      then begin opcode:=18; microcode:=0; found:=true; end;
  839.      if s[i]='I_CLEARMETERS' then begin opcode:=19; microcode:=0; found:=true; end;
  840.  
  841.      {memory addresses}
  842.      if (not found) and (s[i][1]='@') and (s[i][2] in ['0'..'9'])  then
  843.       begin
  844.        opcode:=str2int(rstr(s[i],length(s[i])-1));
  845.        if (opcode<0) or (opcode>(max_ram+1)+(((max_code+1) shl 3)-1)) then
  846.           prog_error(3,s[i]);
  847.        microcode:=1; {variable}
  848.        found:=true;
  849.       end;
  850.  
  851.      {numbers}
  852.      if (not found) and (s[i][1] in ['0'..'9','-'])  then
  853.       begin
  854.        opcode:=str2int(s[i]);
  855.        found:=true;
  856.       end;
  857.  
  858.      if found then
  859.       begin
  860.        code[p].op[i]:=opcode;
  861.        if indirect then microcode:=microcode or 8;
  862.        code[p].op[max_op]:=code[p].op[max_op] or (microcode shl (i*4));
  863.       end
  864.      else if s[i]<>'' then prog_error(2,s[i]);
  865.     end;
  866.   end;
  867.  if show_code then print_code(n,p);
  868.  if compile_by_line then readkey;
  869. end;
  870.  
  871. procedure check_plen(plen:integer);
  872. begin
  873.   if plen>maxcode then
  874.      prog_error(16,#13#10+'Maximum program length exceeded, (Limit: '+
  875.                            cstr(maxcode+1)+' compiled lines)');
  876. end;
  877.  
  878. procedure compile(n:integer;filename:string);
  879. var
  880.  pp:parsetype;
  881.  s,s1,s2,s3,orig_s,msg:string;
  882.  i,j,k,l,linecount,mask,locktype:integer;
  883.  ss:array[0..max_op] of string[16];
  884.  c,lc:char;
  885. begin
  886.  lock_code:='';
  887.  lock_pos:=0;
  888.  locktype:=0;
  889.  lock_dat:=0;
  890.  if not exist(filename) then prog_error(8,filename);
  891.  textcolor(robot_color(n));
  892.  writeln('Compiling robot #',n+1,': ',filename);
  893.  with robot[n]^ do
  894.   begin
  895.    {FIFI}
  896.    is_locked:=false; {assume unlocked robot}
  897.    {/FIFI}
  898.    textcolor(robot_color(n));
  899.    numvars:=0;
  900.    numlabels:=0;
  901.    for k:=0 to max_code do
  902.     for i:=0 to max_op do
  903.      code[k].op[i]:=0;
  904.    plen:=0;
  905.    assign(f,filename);
  906.    reset(f);
  907.    s:='';
  908.    linecount:=0;
  909.  
  910.    {--first pass, compile--}
  911.    while (not eof(f)) and (s<>'#END') {and (plen<=maxcode)} do
  912.     begin
  913.      readln(f,s);
  914.      inc(linecount);
  915.      if locktype<3 then lock_pos:=0;
  916.      if lock_code<>'' then
  917.       for i:=1 to length(s) do
  918.        begin
  919.         inc(lock_pos); if lock_pos>length (lock_code) then lock_pos:=1;
  920.         case locktype of
  921.          3:s[i]:=char((ord(s[i])-1) xor (ord(lock_code[lock_pos]) xor lock_dat));
  922.          2:s[i]:=char(ord(s[i]) xor (ord(lock_code[lock_pos]) xor 1));
  923.          else s[i]:=char(ord(s[i]) xor ord(lock_code[lock_pos]));
  924.         end;
  925.         lock_dat:=ord(s[i]) and 15;
  926.        end;
  927.      s:=btrim(s);
  928.      orig_s:=s;
  929.      for i:=1 to length(s) do
  930.       if s[i] in [#0..#32,',',#128..#255] then s[i]:=' ';
  931.      if show_source and ((lock_code='') or debugging_compiler) then
  932.         writeln(zero_pad(linecount,3)+':'+zero_pad(plen,3)+' ',s);
  933.      if debugging_compiler then
  934.         begin if readkey=#27 then halt; end;
  935.      {-remove comments-}
  936.      k:=0;
  937.      for i:=length(s) downto 1 do
  938.          if s[i]=';' then k:=i;
  939.      if k>0 then s:=lstr(s,k-1);
  940.      s:=btrim(ucase(s));
  941.      for i:=0 to max_op do pp[i]:='';
  942.      if (length(s)>0) and (s[1]<>';') then
  943.       begin
  944.        case s[1] of
  945.         '#':begin (*  Compiler Directives  *)
  946.              s1:=ucase(btrim(rstr(s,length(s)-1)));
  947.              msg:=btrim(rstr(orig_s,length(orig_s)-5));
  948.              k:=0;
  949.              for i:=1 to length(s1) do
  950.               if (k=0) and (s1[i]=' ') then k:=i;
  951.              dec(k);
  952.              if k>1 then
  953.               begin
  954.                s2:=lstr(s1,k);
  955.                s3:=ucase(btrim(rstr(s1,length(s1)-k)));
  956.                k:=0;
  957.                if numvars>0 then
  958.                 for i:=1 to numvars do
  959.                  if s3=varname[i] then k:=i;
  960.                if (s2='DEF') and (numvars<max_vars) then
  961.                 begin
  962.                  if length(s3)>max_var_len then prog_error(12,s3)
  963.                   else
  964.                  if k>0 then prog_error(11,s3)
  965.                   else
  966.                    begin
  967.                     inc(numvars);
  968.                     if numvars>max_vars then prog_error(14,'')
  969.                      else begin
  970.                            varname[numvars]:=s3;
  971.                            varloc [numvars]:=127+numvars;
  972.                           end;
  973.                    end;
  974.                 end
  975.                else if (lstr(s2,4)='LOCK') then
  976.                 begin
  977.                  {FIFI}
  978.                  is_locked:=true; {this robot is locked}
  979.                  {/FIFI}
  980.                  if length(s2)>4 then locktype:=value(rstr(s2,length(s2)-4));
  981.                  lock_code:=btrim(ucase(s3));
  982.                  writeln('Robot is of LOCKed format from this point forward. [',locktype,']');
  983.                  {writeln('Using key: "',lock_code,'"');}
  984.                  for i:=1 to length(lock_code) do
  985.                   lock_code[i]:=char(ord(lock_code[i])-65);
  986.                 end
  987.                else if (s2='MSG') then name:=msg
  988.                else if (s2='TIME') then
  989.                 begin
  990.                  robot_time_limit:=value(s3);
  991.                  if robot_time_limit<0 then robot_time_limit:=0;
  992.                 end
  993.                else if (s2='CONFIG') then
  994.                 begin
  995.                  if (lstr(s3,8)='SCANNER=') then config.scanner:=
  996.                      value(rstr(s3,length(s3)-8))
  997.                  else if (lstr(s3,7)='SHIELD=') then config.shield:=
  998.                          value(rstr(s3,length(s3)-7))
  999.                  else if (lstr(s3,7)='WEAPON=') then config.weapon:=
  1000.                          value(rstr(s3,length(s3)-7))
  1001.                  else if (lstr(s3,6)='ARMOR=') then config.armor:=
  1002.                          value(rstr(s3,length(s3)-6))
  1003.                  else if (lstr(s3,7)='ENGINE=') then config.engine:=
  1004.                          value(rstr(s3,length(s3)-7))
  1005.                  else if (lstr(s3,10)='HEATSINKS=') then config.heatsinks:=
  1006.                          value(rstr(s3,length(s3)-10))
  1007.                  else if (lstr(s3,6)='MINES=') then config.mines:=
  1008.                          value(rstr(s3,length(s3)-6))
  1009.                  else prog_error(20,s3);
  1010.                  with config do
  1011.                    begin
  1012.                      if scanner<0 then scanner:=0; if scanner>5 then scanner:=5;
  1013.                      if shield<0 then shield:=0;   if shield>5 then shield:=5;
  1014.                      if weapon<0 then weapon:=0;   if weapon>5 then weapon:=5;
  1015.                      if armor<0 then armor:=0;     if armor>5 then armor:=5;
  1016.                      if engine<0 then engine:=0;   if engine>5 then engine:=5;
  1017.                      if heatsinks<0 then heatsinks:=0; if heatsinks>5 then heatsinks:=5;
  1018.                      if mines<0 then mines:=0;     if mines>5 then mines:=5;
  1019.                    end;
  1020.                 end
  1021.                else writeln('Warning: unknown directive "'+s2+'"');
  1022.               end;
  1023.             end;
  1024.         '*':begin  (*  Inline Pre-Compiled Machine Code  *)
  1025.              check_plen(plen);
  1026.              for i:=0 to max_op do pp[i]:='';
  1027.              for i:=2 to length(s) do
  1028.               if s[i]='*' then prog_error(23,s);
  1029.              k:=0; i:=1; s1:='';
  1030.              if length(s)<=2 then prog_error(22,s);
  1031.              while (i<length(s)) and (k<=max_op) do
  1032.               begin
  1033.                inc(i);
  1034.                if ord(s[i]) in [33..41,43..127] then pp[k]:=pp[k]+s[i]
  1035.                  else if (ord(s[i]) in [0..32,128..255]) and
  1036.                          (ord(s[i-1]) in [33..41,43..127]) then inc(k);
  1037.               end;
  1038.              for i:=0 to max_op do
  1039.               code[plen].op[i]:=str2int(pp[i]);
  1040.              inc(plen);
  1041.             end;
  1042.         ':':begin  (*  :labels  *)
  1043.              check_plen(plen);
  1044.              s1:=rstr(s,length(s)-1);
  1045.              for i:=1 to length(s1) do
  1046.               if not (s1[i] in ['0'..'9']) then
  1047.                  prog_error(1,s);
  1048.              code[plen].op[0]:=str2int(s1);
  1049.              code[plen].op[max_op]:=2;
  1050.              if show_code then print_code(n,plen);
  1051.              inc(plen);
  1052.             end;
  1053.         '!':begin (*  !labels  *)
  1054.              check_plen(plen);
  1055.              s1:=btrim(rstr(s,length(s)-1));
  1056.              k:=0;
  1057.              for i:=length(s1) downto 1 do
  1058.                  if s1[i] in [';',#8,#9,#10,' ',','] then k:=i;
  1059.              if k>0 then s1:=lstr(s1,k-1);
  1060.              k:=0;
  1061.              for i:=1 to numlabels do
  1062.               if (labelname[i]=s1) then
  1063.                begin
  1064.                 if (labelnum[i]>=0) then prog_error(13,'"!'+s1+'" ('+cstr(labelnum[i])+')');
  1065.                 k:=i;
  1066.                end;
  1067.              if (k=0) then
  1068.               begin
  1069.                inc(numlabels);
  1070.                if numlabels>max_labels then prog_error(15,'');
  1071.                k:=numlabels;
  1072.               end;
  1073.              labelname[k]:=s1;
  1074.              labelnum [k]:=plen;
  1075.             end;
  1076.         else begin  (*  Instructions/Numbers  *)
  1077.               check_plen(plen);
  1078.               {-parse instruction-}
  1079.               {-remove comments-}
  1080.               k:=0;
  1081.               for i:=length(s) downto 1 do
  1082.                   if s[i]=';' then k:=i;
  1083.               if k>0 then s:=lstr(s,k-1);
  1084.               {-setup variables for parsing-}
  1085.               k:=0; for j:=0 to max_op do pp[j]:='';
  1086.               for j:=1 to length(s) do
  1087.                begin
  1088.                 c:=s[j];
  1089.                 if (not (c in [' ',#8,#9,#10,','])) and (k<=max_op) then pp[k]:=pp[k]+c
  1090.                    else if not (lc in [' ',#8,#9,#10,',']) then k:=k+1;
  1091.                 lc:=c;
  1092.                end;
  1093.               parse1(n,plen,pp);
  1094.               inc(plen);
  1095.              end;
  1096.        end;
  1097.       end;
  1098.     end;
  1099.    close(f);
  1100.    {-Add our implied NOP if there's room. This was originally to make sure
  1101.      no one tries using an empty robot program, kinda pointless otherwise-}
  1102.    if plen<=maxcode then
  1103.     begin
  1104.      for i:=0 to max_op do pp[i]:='';
  1105.      pp[0]:='NOP';
  1106.      parse1(n,plen,pp);
  1107.     end
  1108.    else
  1109.     dec(plen); 
  1110.  
  1111.  
  1112.    {--second pass, resolving !labels--}
  1113.    if numlabels>0 then
  1114.     for i:=0 to plen do
  1115.      for j:=0 to max_op-1 do
  1116.       if code[i].op[max_op] shr (j*4)=3 {unresolved !label} then
  1117.        begin
  1118.         k:=code[i].op[j];
  1119.         if (k>0) and (k<=numlabels) then
  1120.          begin
  1121.           l:=labelnum[k];
  1122.           if (l<0) then prog_error(19,'"!'+labelname[k]+'" ('+cstr(l)+')');
  1123.           if (l<0) or (l>maxcode) then prog_error(18,'"!'+labelname[k]+'" ('+cstr(l)+')')
  1124.            else
  1125.             begin
  1126.              code[i].op[j]:=l;
  1127.              mask:=not($F shl (j*4));
  1128.              code[i].op[max_op]:=(code[i].op[max_op] and mask) or (4 shl (j*4));
  1129.                                   {resolved !label}
  1130.             end;
  1131.          end
  1132.         else prog_error(17,cstr(k));
  1133.        end;
  1134.   end;
  1135.  textcolor(7);
  1136. end;
  1137.  
  1138. procedure robot_config(n:integer);
  1139. var
  1140.  i,j,k:integer;
  1141. begin
  1142.  with robot[n]^ do
  1143.   begin
  1144.    case config.scanner of
  1145.     5:scanrange:=1500;
  1146.     4:scanrange:=1000;
  1147.     3:scanrange:=700;
  1148.     2:scanrange:=500;
  1149.     1:scanrange:=350;
  1150.     else scanrange:=250;
  1151.    end;
  1152.    case config.weapon of
  1153.     5:shotstrength:=1.5;
  1154.     4:shotstrength:=1.35;
  1155.     3:shotstrength:=1.2;
  1156.     2:shotstrength:=1;
  1157.     1:shotstrength:=0.8;
  1158.     else shotstrength:=0.5;
  1159.    end;
  1160.    case config.armor of
  1161.     5:begin damageadj:=0.66; speedadj:=0.66; end;
  1162.     4:begin damageadj:=0.77; speedadj:=0.75; end;
  1163.     3:begin damageadj:=0.83; speedadj:=0.85; end;
  1164.     2:begin damageadj:=1; speedadj:=1; end;
  1165.     1:begin damageadj:=1.5; speedadj:=1.2; end;
  1166.     else begin damageadj:=2; speedadj:=1.33; end;
  1167.    end;
  1168.    case config.engine of
  1169.     5:speedadj:=speedadj*1.5;
  1170.     4:speedadj:=speedadj*1.35;
  1171.     3:speedadj:=speedadj*1.2;
  1172.     2:speedadj:=speedadj*1;
  1173.     1:speedadj:=speedadj*0.8;
  1174.     else speedadj:=speedadj*0.5;
  1175.    end;
  1176.    {heatsinks are handled seperately}
  1177.    case config.mines of
  1178.     5:mines:=24;
  1179.     4:mines:=16;
  1180.     3:mines:=10;
  1181.     2:mines:=6;
  1182.     1:mines:=4;
  1183.     else begin mines:=2; config.mines:=0; end;
  1184.    end;
  1185.    shields_up:=false;
  1186.    if (config.shield<3) or (config.shield>5) then config.shield:=0;
  1187.    if (config.heatsinks<0) or (config.heatsinks>5) then config.heatsinks:=0;
  1188.   end;
  1189. end;
  1190.  
  1191. procedure reset_software(n:integer);
  1192. var
  1193.  i:integer;
  1194. begin
  1195.  with robot[n]^ do
  1196.   begin
  1197.    for i:=0 to max_ram do ram[i]:=0;
  1198.    for i:=1 to max_stack do stack[i]:=0;
  1199.    thd:=hd;  tspd:=0;
  1200.    scanarc:=8; shift:=0; err:=0;
  1201.    overburn:=false; keepshift:=false;
  1202.    ip:=0; accuracy:=0;
  1203.    meters:=0;
  1204.    delay_left:=0; time_left:=0;
  1205.    shields_up:=false;
  1206.   end;
  1207. end;
  1208.  
  1209. procedure reset_hardware(n:integer);
  1210. var
  1211.  i:integer;
  1212.  d,dd:real;
  1213. begin
  1214.  with robot[n]^ do
  1215.   begin
  1216.    for i:=1 to max_robot_lines do
  1217.     begin ltx[i]:=0; tx[i]:=0; lty[i]:=0; ty[i]:=0; end;
  1218.    repeat
  1219.     x:=random(1000); y:=random(1000);
  1220.     dd:=1000;
  1221.     for i:=0 to num_robots do
  1222.      begin
  1223.       if robot[i]^.x<0 then robot[i]^.x:=0;
  1224.       if robot[i]^.x>1000 then robot[i]^.x:=1000;
  1225.       if robot[i]^.y<0 then robot[i]^.y:=0;
  1226.       if robot[i]^.y>1000 then robot[i]^.y:=1000;
  1227.       d:=distance(x,y,robot[i]^.x,robot[i]^.y);
  1228.       if (robot[i]^.armor>0) and (i<>n) and (d<dd) then dd:=d;
  1229.      end;
  1230.    until dd>32;
  1231.    for i:=0 to max_mines do
  1232.     with mine[i] do
  1233.      begin x:=-1; y:=-1; yield:=0; detonate:=false; detect:=0; end;
  1234.    lx:=-1; ly:=-1;
  1235.    hd:=random(256); shift:=0;
  1236.    lhd:=hd+1; lshift:=shift+1;
  1237.    spd:=0; speed:=0;
  1238.    cooling:=false;
  1239.    armor:=100; larmor:=0;
  1240.    heat:=0; lheat:=1;
  1241.    match_shots:=0;
  1242.    won:=false;
  1243.    last_damage:=0;
  1244.    last_hit:=0;
  1245.    transponder:=n+1;
  1246.    meters:=0;
  1247.    shutdown:=400;
  1248.    shields_up:=false;
  1249.    channel:=transponder;
  1250.    startkills:=kills;
  1251.    robot_config(n);
  1252.   end;
  1253. end;
  1254.  
  1255. procedure init_robot(n:integer);
  1256. var
  1257.  i,j,k,l:integer;
  1258. begin
  1259.  with robot[n]^ do
  1260.   begin
  1261.    wins:=0; trials:=0; kills:=0; deaths:=0; shots_fired:=0; match_shots:=0;
  1262.    hits:=0; damage_total:=0; cycles_lived:=0; error_count:=0;
  1263.    plen:=0; max_time:=0;
  1264.    name:=''; fn:='';
  1265.    speed:=0;
  1266.    arc_count:=0;
  1267.    sonar_count:=0;
  1268.    robot_time_limit:=0;
  1269.    scanrange:=1500;
  1270.    shotstrength:=1;
  1271.    damageadj:=1;
  1272.    speedadj:=1;
  1273.    mines:=0;
  1274.    with config do
  1275.     begin
  1276.      scanner:=5;
  1277.      weapon:=2;
  1278.      armor:=2;
  1279.      engine:=2;
  1280.      heatsinks:=1;
  1281.      shield:=0;
  1282.      mines:=0;
  1283.     end;
  1284.    for i:=0 to max_ram do ram[i]:=0;
  1285.    for i:=1 to max_stack do stack[i]:=0;
  1286.    for i:=0 to max_code do
  1287.     for k:=0 to max_op do
  1288.      code[i].op[k]:=0;
  1289.    reset_hardware(n);
  1290.    reset_software(n);
  1291.   end;
  1292. end;
  1293.  
  1294. procedure create_robot(n:integer; filename:string);
  1295. var
  1296.  i,j,k:integer;
  1297. begin
  1298.  if maxavail<sizeof(robot_rec) then prog_error(9,base_name(no_path(filename)));
  1299.  new(robot[n]);
  1300.  with robot[n]^ do
  1301.   begin
  1302.    init_robot(n);
  1303.    filename:=ucase(btrim(filename));
  1304.    if filename=base_name(filename) then
  1305.     begin
  1306.      if filename[1]='?' then filename:=filename+locked_ext
  1307.                         else filename:=filename+robot_ext;
  1308.     end;
  1309.    if filename[1]='?' then filename:=rstr(filename,length(filename)-1);
  1310.    fn:=base_name(no_path(filename));
  1311.    compile(n,filename);
  1312.    robot_config(n);
  1313.    with config do
  1314.     begin
  1315.      k:=scanner+armor+weapon+engine+heatsinks+shield+mines;
  1316.      if (k)>max_config_points then
  1317.         prog_error(21,cstr(k)+'/'+cstr(max_config_points));
  1318.     end;
  1319.   end;
  1320. end;
  1321.  
  1322. procedure shutdown;
  1323. var
  1324.   i,j,k:integer;
  1325. begin
  1326.  graph_mode(false);
  1327.  if show_cnotice then
  1328.   begin
  1329.    textcolor(3);
  1330.    write  (progname,' ',version,' ');
  1331.    writeln(cnotice1);
  1332.    writeln(cnotice2);
  1333.   end;
  1334.  textcolor(7);
  1335.  if not registered then begin textcolor(4); writeln('Unregistered version'); end
  1336.                    else writeln('Registered to: ',reg_name);
  1337.  textcolor(7);
  1338.  writeln;
  1339.  if logging_errors then
  1340.   for i:=0 to num_robots do
  1341.    with robot[i]^ do
  1342.     begin
  1343.      writeln('Robot error-log created: ',base_name(fn)+'.ERR');
  1344.      close(errorlog);
  1345.     end;
  1346.  halt;
  1347. end;
  1348.  
  1349. procedure delete_compile_report;
  1350. begin
  1351.  if exist(main_filename+compile_ext) then
  1352.    delete_file(main_filename+compile_ext);
  1353. end;
  1354.  
  1355. procedure write_compile_report;
  1356. var
  1357.  f:text;
  1358.  i,j,k:integer;
  1359. begin
  1360.  assign(f,main_filename+compile_ext);
  1361.  rewrite(f);
  1362.  writeln(f,num_robots+1);
  1363.  for i:=0 to num_robots do
  1364.   with robot[i]^ do
  1365.    writeln(f,fn);
  1366.  close(f);
  1367.  textcolor(15);
  1368.  writeln;
  1369.  writeln('All compiles successful!');
  1370.  writeln;
  1371.  shutdown;
  1372. end;
  1373.  
  1374.  
  1375. procedure parse_param(s:String);
  1376. var
  1377.  f:text;
  1378.  fn,s1:string;
  1379.  found:boolean;
  1380. begin
  1381.  found:=false;
  1382.  s:=btrim(ucase(s));
  1383.  if s='' then exit;
  1384.  if s[1]='#' then
  1385.   begin
  1386.    fn:=rstr(s,length(s)-1);
  1387.    if fn=base_name(fn) then fn:=fn+config_ext;
  1388.    if not exist(fn) then prog_error(6,fn);
  1389.    assign(f,fn); reset(f);
  1390.    while not eof(f) do
  1391.     begin
  1392.      readln(f,s1);
  1393.      s1:=ucase(btrim(s1));
  1394.      if s1[1]='#' then prog_error(7,s1)
  1395.         else parse_param(s1);
  1396.     end;
  1397.    close(f);
  1398.    found:=true;
  1399.   end
  1400.  else if s[1] in ['/','-','='] then
  1401.   begin
  1402.    s1:=rstr(s,length(s)-1);
  1403.    {FIFI}
  1404.    if s1[1]='X' then
  1405.     begin
  1406.      step_mode:=value(rstr(s1,length(s1)-1));
  1407.      found:=true;
  1408.      if step_mode=0 then step_mode:=1;
  1409.      if (step_mode<1) or (step_mode>9) then prog_error(24,rstr(s1,length(s1)-1));
  1410.     end;
  1411.    {/FIFI}
  1412.    if s1[1]='D' then begin game_delay:=value(rstr(s1,length(s1)-1)); found:=true; end;
  1413.    if s1[1]='T' then begin time_slice:=value(rstr(s1,length(s1)-1)); found:=true; end;
  1414.    if s1[1]='L' then begin game_limit:=value(rstr(s1,length(s1)-1))*1000; found:=true; end;
  1415.    if s1[1]='Q' then begin sound_on:=false; found:=true; end;
  1416.    if s1[1]='M' then begin matches:=value(rstr(s1,length(s1)-1)); found:=true; end;
  1417.    if s1[1]='S' then begin show_source:=false; found:=true; end;
  1418.    if s1[1]='G' then begin no_gfx:=true; found:=true; end;
  1419.    if s1[1]='R' then begin report:=true; found:=true;
  1420.                      if (length(s1)>1) then
  1421.                         report_type:=value(rstr(s1,length(s1)-1)); end;
  1422.    if s1[1]='C' then begin compile_only:=true; found:=true; end;
  1423.    if s1[1]='^' then begin show_cnotice:=false; found:=true; end;
  1424.    if s1[1]='A' then begin show_arcs:=true; found:=true; end;
  1425.    if s1[1]='W' then begin windoze:=false; found:=true; end;
  1426.    if s1[1]='$' then begin debug_info:=true; found:=true; end;
  1427.    if s1[1]='#' then begin maxcode:=value(rstr(s1,length(s1)-1))-1; found:=true; end;
  1428.    if s1[1]='!' then begin insane_missiles:=true; if (length(s1)>1) then
  1429.                      insanity:=value(rstr(s1,length(s1)-1)); found:=true; end;
  1430.    if s1[1]='@' then begin old_shields:=true; found:=true; end;
  1431.    if s1[1]='E' then begin logging_errors:=true; found:=true; end;
  1432.    if insanity<0 then insanity:=0;
  1433.    if insanity>15 then insanity:=15;
  1434.   end
  1435.  else if s[1]=';' then found:=true
  1436.  else if (num_robots<max_robots) and (s<>'') then
  1437.   begin
  1438.    inc(num_robots);
  1439.    create_robot(num_robots,s);
  1440.    found:=true;
  1441.    if num_robots=max_robots then writeln('Maximum number of robots reached.');
  1442.   end
  1443.    else prog_error(10,'');
  1444.  if not found then prog_error(8,s);
  1445. end;
  1446.  
  1447.  
  1448. procedure init;
  1449. var
  1450.  i:integer;
  1451. begin
  1452.  if debugging_compiler or compile_by_line or show_code then
  1453.   begin write('!!! Warning !!! Compiler Debugging enabled !!!'); flushkey; readkey; writeln; end;
  1454.  {FIFI}
  1455.  step_mode:=0; {stepping disabled}
  1456.  {/FIFI}
  1457.  logging_errors:=false; stats_mode:=0;
  1458.  insane_missiles:=false; insanity:=0;
  1459.  delay_per_sec:=0; windoze:=true;
  1460.  graphix:=false; no_gfx:=false;
  1461.  sound_on:=true; timing:=true;
  1462.  matches:=1; played:=0; old_shields:=false;
  1463.  quit:=false; compile_only:=false;
  1464.  show_arcs:=false; debug_info:=false;
  1465.  show_cnotice:=true;
  1466.  show_source:=true;
  1467.  report:=false;
  1468.  kill_count:=0;
  1469.  maxcode:=max_code;
  1470.  make_tables;
  1471.  randomize;
  1472.  num_robots:=-1;
  1473.  game_limit:=100000;
  1474.  game_cycle:=0;
  1475.  game_delay:=default_delay;
  1476.  time_slice:=default_slice;
  1477.  for i:=0 to max_missiles do
  1478.   with missile[i] do
  1479.    begin a:=0; source:=-1; x:=0; y:=0; lx:=0; ly:=0; mult:=1; end;
  1480.  
  1481.  registered:=false;
  1482.  reg_name:='Unregistered';
  1483.  reg_num:=$FFFF;
  1484.  check_registration;
  1485.  
  1486.  writeln; textcolor(3);
  1487.  write  (progname,' ',version,' ');
  1488.  writeln(cnotice1);
  1489.  writeln(cnotice2);
  1490.  textcolor(7);
  1491.  if not registered then begin textcolor(4); writeln('Unregistered version'); end
  1492.                    else writeln('Registered to: ',reg_name);
  1493.  textcolor(7);
  1494.  writeln;
  1495.  {create_robot(0,'SDUCK');}
  1496.  
  1497.  delete_compile_report;
  1498.  if paramcount>0 then
  1499.   for i:=1 to paramcount do
  1500.    parse_param(btrim(ucase(paramstr(i))))
  1501.  else prog_error(5,'');
  1502.  {FIFI}
  1503.  temp_mode:=step_mode;  {store initial step_mode}
  1504.  {/FIFI}
  1505.  if logging_errors then
  1506.   for i:=0 to num_robots do
  1507.    with robot[i]^ do
  1508.     begin
  1509.      assign(errorlog,base_name(fn)+'.ERR');
  1510.      rewrite(errorlog);
  1511.     end;
  1512.  if compile_only then write_compile_report;
  1513.  if num_robots<1 then prog_error(4,'');
  1514.  
  1515.  if not no_gfx then graph_mode(true);
  1516.  
  1517.  {--fix ups--}
  1518.  if matches>100000 then matches:=100000;
  1519.  if matches<1 then matches:=1;
  1520.  if game_delay>1000 then game_delay:=1000;
  1521.  if game_delay<0 then game_delay:=0;
  1522.  if time_slice>100 then time_slice:=100;
  1523.  if time_slice<1 then time_slice:=1;
  1524.  if game_limit<0 then game_limit:=0;
  1525.  if game_limit>100000 then game_limit:=100000;
  1526.  if maxcode<1 then maxcode:=1; {0 based, so actually 2 lines}
  1527.  if maxcode>max_code then maxcode:=max_code;
  1528.  
  1529.  {--Just to avoid floating pointers--}
  1530.  for i:=num_robots+1 to max_robots+2 do
  1531.   robot[i]:=robot[0];
  1532.  robot[-1]:=robot[0];
  1533.  robot[-2]:=robot[0];
  1534.  
  1535.  if not graphix then
  1536.   begin
  1537.    writeln('Freemem: ',memavail);
  1538.    writeln;
  1539.   end;
  1540. end;
  1541.  
  1542. procedure draw_robot(n:integer);
  1543. var
  1544.  i,t:integer;
  1545.  xx,yy:real;
  1546. begin
  1547.  if not (n in [0..num_robots]) then exit;
  1548.  with robot[n]^ do
  1549.   begin
  1550.    if x>1000 then x:=1000;
  1551.    if y>1000 then y:=1000;
  1552.    if x<0 then x:=0;
  1553.    if y<0 then y:=0;
  1554.    {if (lhd=hd) and (lx=x) and (ly=y) then exit;}
  1555.  
  1556.    {--set up for erase--}
  1557.    {xx:=lx*screen_scale; yy:=ly*screen_scale;
  1558.    lhd:=(lhd+1024) and 255;
  1559.    ltx[1]:=round(xx+sint[lhd]*robot_scale);
  1560.    lty[1]:=round(yy-cost[lhd]*robot_scale);
  1561.    ltx[2]:=round(xx+sint[(lhd+$68) and 255]*robot_scale);
  1562.    lty[2]:=round(yy-cost[(lhd+$68) and 255]*robot_scale);
  1563.    ltx[3]:=round(xx+sint[(lhd+$98) and 255]*robot_scale);
  1564.    lty[3]:=round(yy-cost[(lhd+$98) and 255]*robot_scale);
  1565.    t:=(lhd+(lshift and 255)+1024) and 255;
  1566.    ltx[4]:=round(xx+sint[t and 255]*robot_scale);
  1567.    lty[4]:=round(yy-cost[t and 255]*robot_scale);}
  1568.  
  1569.    {--set up for draw--}
  1570.    xx:=x*screen_scale+screen_x; yy:=y*screen_scale+screen_y;
  1571.    hd:=(hd+1024) and 255;
  1572.    tx[1]:=round(xx+sint[hd]*5);
  1573.    ty[1]:=round(yy-cost[hd]*5);
  1574.    tx[2]:=round(xx+sint[(hd+$68) and 255]*robot_scale);
  1575.    ty[2]:=round(yy-cost[(hd+$68) and 255]*robot_scale);
  1576.    tx[3]:=round(xx+sint[(hd+$98) and 255]*robot_scale);
  1577.    ty[3]:=round(yy-cost[(hd+$98) and 255]*robot_scale);
  1578.    t:=(hd+(shift and 255)+1024) and 255;
  1579.    tx[4]:=round(xx); ty[4]:=round(yy);
  1580.    tx[5]:=round(xx+sint[t]*robot_scale*0.8);
  1581.    ty[5]:=round(yy-cost[t]*robot_scale*0.8);
  1582.    tx[6]:=round(xx+sint[(t+scanarc+1024) and 255]*scanrange*screen_scale);
  1583.    ty[6]:=round(yy-cost[(t+scanarc+1024) and 255]*scanrange*screen_scale);
  1584.    tx[7]:=round(xx+sint[(t-scanarc+1024) and 255]*scanrange*screen_scale);
  1585.    ty[7]:=round(yy-cost[(t-scanarc+1024) and 255]*scanrange*screen_scale);
  1586.    startarc:=round(((256-((t+scanarc+1024) and 255))/256*360)+90);
  1587.    endarc:=round(((256-((t-scanarc+1024) and 255))/256*360)+90);
  1588.  
  1589.  
  1590.    if graphix then
  1591.     begin
  1592.      main_viewport;
  1593.      {--erase--}
  1594.      setcolor(0);
  1595.      if lshields then
  1596.         circle(ltx[4],lty[4],robot_scale);
  1597.      if (arc_count>0) then
  1598.       begin
  1599.        line(ltx[4],lty[4],ltx[6],lty[6]);
  1600.        line(ltx[4],lty[4],ltx[7],lty[7]);
  1601.        if scanrange<1500 then
  1602.           arc(ltx[4],lty[4],lstartarc,lendarc,round(scanrange*screen_scale));
  1603.       end;
  1604.      if (sonar_count>0) then
  1605.       begin
  1606.        circle(ltx[4],lty[4],round(max_sonar*screen_scale));
  1607.       end;
  1608.      if armor>0 then 
  1609.       begin {only erase body if still alive, that way we leave a "corpse" when dead}
  1610.        line(ltx[1],lty[1],ltx[2],lty[2]);
  1611.        line(ltx[2],lty[2],ltx[3],lty[3]);
  1612.        line(ltx[3],lty[3],ltx[1],lty[1]);
  1613.        line(ltx[4],lty[4],ltx[5],lty[5]);
  1614.       end;
  1615.     end;
  1616.    if armor>0 then {If we're still alive we need to redraw}
  1617.     begin
  1618.      if arc_count>0   then dec(arc_count);
  1619.      if sonar_count>0 then dec(sonar_count);
  1620.      if graphix then
  1621.       begin
  1622.        {--draw--}
  1623.        setcolor(robot_color(n) and 7);
  1624.        if shields_up then
  1625.         circle(tx[4],ty[4],robot_scale);
  1626.        setcolor(robot_color(n));
  1627.        line(tx[1],ty[1],tx[2],ty[2]);
  1628.        line(tx[2],ty[2],tx[3],ty[3]);
  1629.        line(tx[3],ty[3],tx[1],ty[1]);
  1630.        setcolor(7);
  1631.        line(tx[4],ty[4],tx[5],ty[5]);
  1632.        setcolor(8);
  1633.        if show_arcs and (arc_count>0) then
  1634.         begin
  1635.          line(tx[4],ty[4],tx[6],ty[6]);
  1636.          line(tx[4],ty[4],tx[7],ty[7]);
  1637.          if scanrange<1500 then
  1638.             arc(tx[4],ty[4],startarc,endarc,round(scanrange*screen_scale));
  1639.         end;
  1640.        if show_arcs and (sonar_count>0) then
  1641.           circle(tx[4],ty[4],round(max_sonar*screen_scale));
  1642.      end;
  1643.      lx:=x; ly:=y; lhd:=hd; lshift:=shift; lshields:=shields_up;
  1644.      for i:=1 to max_robot_lines do
  1645.       begin ltx[i]:=tx[i]; lty[i]:=ty[i]; end;
  1646.      lstartarc:=startarc; lendarc:=endarc;
  1647.     end;
  1648.   end;
  1649. end;
  1650.  
  1651. function get_from_ram(n,i,j:integer):integer;
  1652.  var k,l:integer;
  1653. begin
  1654.  with robot[n]^ do
  1655.   begin
  1656.    if (i<0) or (i>(max_ram+1)+(((max_code+1) shl 3)-1)) then
  1657.      begin k:=0; robot_error(n,4,cstr(i)); end
  1658.     else
  1659.      begin
  1660.       if i<=max_ram then k:=ram[i]
  1661.        else
  1662.         begin
  1663.          l:=i-max_ram-1;
  1664.          k:=code[l shr 2].op[l and 3];
  1665.         end;
  1666.      end;
  1667.   end;
  1668.  get_from_ram:=k;
  1669. end;
  1670.  
  1671. function get_val(n,c,o:integer):integer;
  1672. var
  1673.  i,j,k,l:integer;
  1674. begin
  1675.  k:=0;
  1676.  with robot[n]^ do
  1677.   begin
  1678.    j:=(code[c].op[max_op] shr (4*o)) and 15;
  1679.    i:=code[c].op[o];
  1680.    if (j and 7)=1 then
  1681.     begin
  1682.      k:=get_from_ram(n,i,j);
  1683.     end else k:=i;
  1684.    if (j and 8)>0 then
  1685.     k:=get_from_ram(n,k,j);
  1686.   end;
  1687.  get_val:=k;
  1688. end;
  1689.  
  1690. procedure put_val(n,c,o,v:integer);
  1691. var
  1692.  i,j,k:integer;
  1693. begin
  1694.  k:=0; i:=0; j:=0;
  1695.  with robot[n]^ do
  1696.   begin
  1697.    j:=(code[c].op[max_op] shr (4*o)) and 15;
  1698.    i:=code[c].op[o];
  1699.    if (j and 7)=1 then
  1700.     begin
  1701.      if (i<0) or (i>max_ram) then
  1702.        robot_error(n,4,cstr(i))
  1703.       else
  1704.        if (j and 8)>0 then
  1705.         begin
  1706.          i:=ram[i];
  1707.          if (i<0) or (i>max_ram) then
  1708.           robot_error(n,4,cstr(i))
  1709.          else ram[i]:=v;
  1710.         end
  1711.        else ram[i]:=v;
  1712.     end
  1713.    else
  1714.     robot_error(n,3,'');
  1715.   end;
  1716. end;
  1717.  
  1718. procedure push(n,v:integer);
  1719. begin
  1720.  with robot[n]^ do
  1721.   begin
  1722.    if (ram[71]>=0) and (ram[71]<max_stack) then
  1723.     begin
  1724.      inc(ram[71]);
  1725.      stack[ram[71]]:=v;
  1726.     end
  1727.    else robot_error(n,1,cstr(ram[71]));
  1728.   end;
  1729. end;
  1730.  
  1731. function pop(n:integer):integer;
  1732. var
  1733.  k:integer;
  1734. begin
  1735.  with robot[n]^ do
  1736.   begin
  1737.    if (ram[71]>0) and (ram[71]<=max_stack) then
  1738.     begin
  1739.      k:=stack[ram[71]];
  1740.      dec(ram[71]);
  1741.     end
  1742.    else robot_error(n,5,cstr(ram[71]));
  1743.   end;
  1744.  pop:=k;
  1745. end;
  1746.  
  1747. function find_label(n,l,m:integer):integer;
  1748. var
  1749.  i,j,k:integer;
  1750. begin
  1751.  k:=-1;
  1752.  with robot[n]^ do
  1753.   begin
  1754.    if m=3 then robot_error(n,9,'')
  1755.     else
  1756.    if m=4 then k:=l
  1757.     else
  1758.    for i:=plen downto 0 do
  1759.     begin
  1760.      j:=code[i].op[max_op] and 15;
  1761.      if (j=2) and (code[i].op[0]=l) then k:=i;
  1762.     end;
  1763.   end;
  1764.  find_label:=k;
  1765. end;
  1766.  
  1767.  
  1768. procedure init_mine(n,detectrange,size:integer);
  1769. var
  1770.  i,j,k:integer;
  1771. begin
  1772.  with robot[n]^ do
  1773.   begin
  1774.    k:=-1;
  1775.    for i:=0 to max_mines do
  1776.     if ((mine[i].x<0) or (mine[i].x>1000) or (mine[i].y<0) or (mine[i].y>1000)
  1777.        or (mine[i].yield<=0)) and (k<0) then k:=i;
  1778.    if k>=0 then
  1779.     begin
  1780.      mine[k].x:=x;
  1781.      mine[k].y:=y;
  1782.      mine[k].detect:=detectrange;
  1783.      mine[k].yield:=size;
  1784.      mine[k].detonate:=false;
  1785.      click;
  1786.     end;
  1787.   end;
  1788. end;
  1789.  
  1790. function count_missiles:integer;
  1791. var
  1792.  i,k:integer;
  1793. begin
  1794.  k:=0;
  1795.  for i:=0 to max_missiles do
  1796.   if missile[i].a>0 then inc(k);
  1797.  count_missiles:=k;
  1798. end;
  1799.  
  1800. procedure init_missile(xx,yy,xxv,yyv:real; dir,s,blast:integer; ob:boolean);
  1801. var
  1802.  i,j,k:integer;
  1803.  m:real;
  1804.  sound:boolean;
  1805. begin
  1806.  k:=-1; click;
  1807.  for i:=max_missiles downto 0 do
  1808.   if missile[i].a=0 then k:=i;
  1809.  if k>=0 then
  1810.   with missile[k] do
  1811.    begin
  1812.     source:=s;
  1813.     x:=xx; lx:=x;
  1814.     y:=yy; ly:=y;
  1815.     rad:=0; lrad:=0;
  1816.     if ob then mult:=1.25 else mult:=1;
  1817.     if blast>0 then
  1818.       begin max_rad:=blast; a:=2; end
  1819.      else
  1820.       begin
  1821.        if (s>=0) and (s<=num_robots) then
  1822.           mult:=mult*(robot[s]^.shotstrength);
  1823.        m:=mult;
  1824.        if ob then m:=m+0.25;
  1825.        mspd:=missile_spd*mult;
  1826.        if insane_missiles then mspd:=100+(50*insanity)*mult;
  1827.        if (s>=0) and (s<=num_robots) then
  1828.          begin
  1829.           inc(robot[s]^.heat,round(20*m));
  1830.           inc(robot[s]^.shots_fired);
  1831.           inc(robot[s]^.match_shots);
  1832.          end;
  1833.        a:=1; hd:=dir;
  1834.        max_rad:=mis_radius;
  1835.        if debug_info then
  1836.          begin writeln(#13,zero_pad(game_cycle,5),' F ',s,': hd=',hd,'           ');
  1837.          repeat until keypressed; flushkey; end;
  1838.       end;
  1839.    end;
  1840.  (*The following was to see if teh missile array is big enough*)
  1841.   {else
  1842.    begin
  1843.     sound:=sound_on;
  1844.     sound_on:=true;
  1845.     chirp;
  1846.     sound_on:=sound;
  1847.    end;
  1848.  setfillstyle(1,0);
  1849.  setcolor(robot_color(k));
  1850.  bar(5,5,37,12);
  1851.  outtextxy(5,5,cstr(count_missiles));}
  1852. end;
  1853.  
  1854. procedure damage(n,d:integer; physical:boolean);
  1855. var
  1856.  i,k,h,dd:integer;
  1857.  m:real;
  1858. begin
  1859.  if (n<0) or (n>num_robots) or (robot[n]^.armor<=0) then exit;
  1860.  if robot[n]^.config.shield<3 then robot[n]^.shields_up:=false;
  1861.  with robot[n]^ do
  1862.   begin
  1863.    h:=0;
  1864.    if (shields_up) and (not physical) then
  1865.     begin
  1866.      dd:=d;
  1867.      if (old_shields) and (config.shield>=3) then begin d:=0; h:=0; end
  1868.       else case config.shield of
  1869.        3:begin d:=round(dd*2/3); if d<1 then d:=1; h:=round(dd*2/3); end;
  1870.        4:begin h:=trunc(dd/2); d:=dd-h; end;
  1871.        5:begin d:=round(dd*1/3); if d<1 then d:=1;
  1872.                h:=round(dd*1/3); if h<1 then h:=1; end;
  1873.       end;
  1874.     end;
  1875.    if d<0 then d:=0;
  1876.    if debug_info then
  1877.     begin writeln(#13,zero_pad(game_cycle,5),' D ',n,': ',armor,'-',d,'=',armor-d,'           ');
  1878.     repeat until keypressed; flushkey; end;
  1879.    if d>0 then
  1880.     begin d:=round(d*damageadj); if d<1 then d:=1; end;
  1881.    dec(armor,d);
  1882.    inc(heat,h);
  1883.    last_damage:=0;
  1884.    if armor<=0 then
  1885.     begin
  1886.      armor:=0;
  1887.      update_armor(n);
  1888.      heat:=500;
  1889.      update_heat(n);
  1890.      armor:=0;
  1891.      inc(kill_count);
  1892.      inc(deaths);
  1893.      update_lives(n);
  1894.      if graphix and timing then time_delay(10);
  1895.      draw_robot(n);
  1896.      heat:=0;
  1897.      update_heat(n);
  1898.      init_missile(x,y,0,0,0,n,blast_circle,false);
  1899.      if overburn then m:=1.3 else m:=1;
  1900.      for i:=0 to num_robots do
  1901.       if (i<>n) and (robot[i]^.armor>0) then
  1902.        begin
  1903.         k:=round(distance(x,y,robot[i]^.x,robot[i]^.y));
  1904.         if k<blast_radius then
  1905.          damage(i,round(abs(blast_radius-k)*m),false);
  1906.        end;
  1907.     end;
  1908.   end;
  1909. end;
  1910.  
  1911. function scan(n:integer):integer;
  1912. var
  1913.  r,d,acc:real;
  1914.  dir,range,i,j,k,l,nn,xx,yy,sign:integer;
  1915. begin
  1916.  nn:=-1;
  1917.  range:=maxint;
  1918.  if not (n in [0..num_robots]) then exit;
  1919.  with robot[n]^ do
  1920.   begin
  1921.    if scanarc<0 then scanarc:=0;
  1922.    accuracy:=0; nn:=-1;
  1923.    dir:=(shift+hd) and 255;
  1924.    if debug_info then writeln('<SCAN Arc=',scanarc,', Dir=',dir,'>');
  1925.    for i:=0 to num_robots do
  1926.     if (i<>n) and (robot[i]^.armor>0) then
  1927.      begin
  1928.       j:=find_anglei(x,y,robot[i]^.x,robot[i]^.y);
  1929.       d:=distance(x,y,robot[i]^.x,robot[i]^.y);
  1930.       k:=round(d);
  1931.       if (k<range) and (k<=scanrange) and ((abs(j-dir)<=abs(scanarc)) or (abs(j-dir)>=256-abs(scanarc))) then
  1932.        begin
  1933.         dir:=(dir+1024) and 255;
  1934.         xx:=round( sint[dir]*d+x);
  1935.         yy:=round(-cost[dir]*d+y);
  1936.         r:=distance(xx,yy,robot[i]^.x,robot[i]^.y);
  1937.         if debug_info then begin
  1938.           writeln('SCAN HIT! Scan X,Y: ',round(xx),',',round(yy),'  Robot X,Y: ',
  1939.                    round(robot[i]^.x),',',round(robot[i]^.y),'  Dist=',round(r));
  1940.           repeat until keypressed; flushkey; end;
  1941.         if (scanarc>0) or (r<hit_range-2) then
  1942.          begin
  1943.           range:=k;
  1944.           accuracy:=0;
  1945.           if scanarc>0 then
  1946.            begin
  1947.             j:=(j+1024) and 255; dir:=(dir+1024) and 255;
  1948.             if (j<dir) then sign:=-1;
  1949.             if (j>dir) then sign:= 1;
  1950.             if (j>190) and (dir<66) then begin dir:=dir+256; sign:=-1; end;
  1951.             if (dir>190) and (j<66) then begin   j:=  j+256; sign:= 1; end;
  1952.             acc:=abs(j-dir)/scanarc*2;
  1953.             if sign<0 then accuracy:=-abs(round(acc))
  1954.                       else accuracy:=abs(round(acc));
  1955.             if accuracy>2 then accuracy:=2;
  1956.             if accuracy<-2 then accuracy:=-2;
  1957.            end;
  1958.           nn:=i;
  1959.           if debug_info then
  1960.            begin writeln(#13,zero_pad(game_cycle,5),' S ',n,': nn=',nn,', range=',range,', acc=',accuracy,'           ');
  1961.            repeat until keypressed; flushkey; end;
  1962.          end;
  1963.        end;
  1964.      end;
  1965.    if nn in [0..num_robots] then
  1966.     begin
  1967.      ram[5]:=robot[nn]^.transponder;
  1968.      ram[6]:=(robot[nn]^.hd-(hd+shift)+1024) and 255;
  1969.      ram[7]:=robot[nn]^.spd;
  1970.      ram[13]:=round(robot[nn]^.speed*100);
  1971.     end;
  1972.   end;
  1973.  scan:=range;
  1974. end;
  1975.  
  1976. procedure com_transmit(n,chan,data:integer);
  1977. var
  1978.  i,j,k:integer;
  1979. begin
  1980.  for i:=0 to num_robots do
  1981.   with robot[i]^ do
  1982.    if (armor>0) and (i<>n) and (channel=chan) then
  1983.     begin
  1984.      if (ram[10]<0) or (ram[10]>max_queue) then ram[10]:=0;
  1985.      if (ram[11]<0) or (ram[11]>max_queue) then ram[11]:=0;
  1986.      ram[ram[11]+com_queue]:=data;
  1987.      inc(ram[11]);
  1988.      if (ram[11]>max_queue) then ram[11]:=0;
  1989.      if (ram[11]=ram[10]) then inc(ram[10]);
  1990.      if (ram[10]>max_queue) then ram[10]:=0;
  1991.     end;
  1992. end;
  1993.  
  1994. function com_receive(n:integer):integer;
  1995. var
  1996.  i,j,k:integer;
  1997. begin
  1998.  k:=0;
  1999.  with robot[n]^ do
  2000.   begin
  2001.    if (ram[10]<>ram[11]) then
  2002.     begin
  2003.      if (ram[10]<0) or (ram[10]>max_queue) then ram[10]:=0;
  2004.      if (ram[11]<0) or (ram[11]>max_queue) then ram[11]:=0;
  2005.      k:=ram[ram[10]+com_queue];
  2006.      inc(ram[10]);
  2007.      if (ram[10]>max_queue) then ram[10]:=0;
  2008.     end
  2009.    else robot_error(n,12,'');
  2010.   end;
  2011.  com_receive:=k;
  2012. end;
  2013.  
  2014. function in_port(n,p:integer; var time_used:integer):integer;
  2015. var
  2016.  v,i,j,k,l,nn:integer;
  2017. begin
  2018.  v:=0;
  2019.  with robot[n]^ do
  2020.   begin
  2021.    case p of
  2022.     01:v:=spd;
  2023.     02:v:=heat;
  2024.     03:v:=hd;
  2025.     04:v:=shift;
  2026.     05:v:=(shift+hd) and 255;
  2027.     06:v:=armor;
  2028.     07:begin v:=scan(n); inc(time_used); if show_arcs then arc_count:=2; end;
  2029.     08:begin v:=accuracy; inc(time_used); end;
  2030.     09:begin
  2031.         nn:=-1;
  2032.         inc(time_used,3); k:=maxint; nn:=-1;
  2033.         for i:=0 to num_robots do
  2034.          begin
  2035.           j:=round(distance(x,y,robot[i]^.x,robot[i]^.y));
  2036.           if (n<>i) and (j<k) and (robot[i]^.armor>0) then begin k:=j; nn:=i; end;
  2037.          end;
  2038.         v:=k;
  2039.         if nn in [0..num_robots] then
  2040.            ram[5]:=robot[nn]^.transponder;
  2041.        end;
  2042.     10:v:=random(65535)+random(2);
  2043.     16:begin
  2044.         nn:=-1;
  2045.         if show_arcs then sonar_count:=2;
  2046.         inc(time_used,40);
  2047.         l:=-1; k:=maxint; nn:=-1;
  2048.         for i:=0 to num_robots do
  2049.          begin
  2050.           j:=round(distance(x,y,robot[i]^.x,robot[i]^.y));
  2051.           if (n<>i) and (j<k) and (j<max_sonar) and (robot[i]^.armor>0) then
  2052.              begin k:=j; l:=i; nn:=i; end;
  2053.          end;
  2054.         if l>=0 then v:=(round(find_angle(x,y,robot[l]^.x,robot[l]^.y)/pi*128+
  2055.                               1024+random(65)-32) and 255)
  2056.                 else v:=minint;
  2057.         if nn in [0..num_robots] then
  2058.            ram[5]:=robot[nn]^.transponder;
  2059.        end;
  2060.     17:v:=scanarc;
  2061.     18:if overburn then v:=1 else v:=0;
  2062.     19:v:=transponder;
  2063.     20:v:=shutdown;
  2064.     21:v:=channel;
  2065.     22:v:=mines;
  2066.     23:if config.mines>=0 then begin
  2067.         k:=0;
  2068.         for i:=0 to max_mines do
  2069.          with mine[i] do
  2070.           if (x>=0) and (x<=1000) and (y>=0) and (y<=1000) and (yield>0) then inc(k);
  2071.         v:=k;
  2072.        end else v:=0;
  2073.     24:if config.shield>0 then
  2074.         begin if shields_up then v:=1 else v:=0;
  2075.         end else begin v:=0; shields_up:=false; end;
  2076.     else robot_error(n,11,cstr(p));
  2077.    end;
  2078.   end;
  2079.  in_port:=v;
  2080. end;
  2081.  
  2082. procedure out_port(n,p,v:integer; var time_used:integer);
  2083. var
  2084.  i:integer;
  2085. begin
  2086.  with robot[n]^ do
  2087.   begin
  2088.    case p of
  2089.     11:tspd:=v;
  2090.     12:shift:=(shift+v+1024) and 255;
  2091.     13:shift:=(v+1024) and 255;
  2092.     14:thd:=(thd+v+1024) and 255;
  2093.     15:begin
  2094.         inc(time_used,3);
  2095.         if v>4 then v:=4;
  2096.         if v<-4 then v:=-4;
  2097.         init_missile(x,y,xv,yv,(hd+shift+v) and 255,n,0,overburn);
  2098.        end;
  2099.     17:scanarc:=v;
  2100.     18:if v=0 then overburn:=false else overburn:=true;
  2101.     19:transponder:=v;
  2102.     20:shutdown:=v;
  2103.     21:channel:=v;
  2104.     22:if config.mines>=0 then
  2105.         begin if mines>0 then begin init_mine(n,v,mine_blast); dec(mines); end else robot_error(n,14,'');
  2106.         end else robot_error(n,13,'');
  2107.     23:if config.mines>=0 then
  2108.         begin for i:=0 to max_mines do mine[i].detonate:=true;
  2109.         end else robot_error(n,13,'');
  2110.     24:if config.shield>=3 then
  2111.         begin if v=0 then shields_up:=false else shields_up:=true;
  2112.         end else begin shields_up:=false; robot_error(n,15,''); end;
  2113.     else robot_error(n,11,cstr(p));
  2114.    end;
  2115.    if scanarc>64 then scanarc:=64; if scanarc<0 then scanarc:=0;
  2116.   end;
  2117. end;
  2118.  
  2119. procedure call_int(n,int_num:integer; var time_used:integer);
  2120. var
  2121.  i,j,k:integer;
  2122. begin
  2123.  with robot[n]^ do
  2124.   begin
  2125.    case int_num of
  2126.     00:damage(n,1000,true);
  2127.     01:begin
  2128.         reset_software(n);
  2129.         time_used:=10;
  2130.        end;
  2131.     02:begin
  2132.         time_used:=5;
  2133.         ram[69]:=round(x);
  2134.         ram[70]:=round(y);
  2135.        end;
  2136.     03:begin
  2137.         time_used:=2;
  2138.         if ram[65]=0 then keepshift:=false else keepshift:=true;
  2139.         ram[70]:=shift and 255;
  2140.        end;
  2141.     04:begin
  2142.         if ram[65]=0 then overburn:=false else overburn:=true;
  2143.        end;
  2144.     05:begin
  2145.         time_used:=2;
  2146.         ram[70]:=transponder;
  2147.        end;
  2148.     06:begin
  2149.         time_used:=2;
  2150.         ram[69]:=game_cycle shr 16;
  2151.         ram[70]:=game_cycle and 65535;
  2152.        end;
  2153.     07:begin
  2154.         j:=ram[69]; k:=ram[70];
  2155.         if j<0 then j:=0; if j>1000 then j:=1000;
  2156.         if k<0 then k:=0; if k>1000 then k:=1000;
  2157.         ram[65]:=round(find_angle(round(x),round(y),j,k)/pi*128+256) and 255;
  2158.         time_used:=32;
  2159.        end;
  2160.     08:begin
  2161.         ram[70]:=ram[5];
  2162.         time_used:=1;
  2163.        end;
  2164.     09:begin
  2165.         ram[69]:=ram[6];
  2166.         ram[70]:=ram[7];
  2167.         time_used:=2;
  2168.        end;
  2169.     10:begin
  2170.         k:=0;
  2171.         for i:=0 to num_robots do
  2172.          if robot[i]^.armor>0 then inc(k);
  2173.         ram[68]:=k;
  2174.         ram[69]:=played;
  2175.         ram[70]:=matches;
  2176.         time_used:=4;
  2177.        end;
  2178.     11:begin
  2179.         ram[68]:=round(speed*100);
  2180.         ram[69]:=last_damage;
  2181.         ram[70]:=last_hit;
  2182.         time_used:=5;
  2183.        end;
  2184.     12:begin
  2185.         ram[70]:=ram[8];
  2186.         time_used:=1;
  2187.        end;
  2188.     13:begin
  2189.         ram[8]:=0;
  2190.         time_used:=1;
  2191.        end;
  2192.     14:begin
  2193.         com_transmit(n,channel,ram[65]);
  2194.         time_used:=1;
  2195.        end;
  2196.     15:begin
  2197.         if (ram[10]<>ram[11]) then
  2198.          ram[70]:=com_receive(n)
  2199.         else
  2200.          robot_error(n,12,'');
  2201.         time_used:=1;
  2202.        end;
  2203.     16:begin
  2204.         if (ram[11]>=ram[10]) then
  2205.          ram[70]:=ram[11]-ram[10]
  2206.         else
  2207.          begin
  2208.           ram[70]:=max_queue+1-ram[10]+ram[11];
  2209.          end;
  2210.         time_used:=1;
  2211.        end;
  2212.     17:begin
  2213.         ram[10]:=0;
  2214.         ram[11]:=0;
  2215.         time_used:=1;
  2216.        end;
  2217.     18:begin
  2218.         ram[68]:=kills;
  2219.         ram[69]:=kills-startkills;
  2220.         ram[70]:=deaths;
  2221.         time_used:=3;
  2222.        end;
  2223.     19:begin ram[9]:=0; meters:=0; end;
  2224.     else robot_error(n,10,cstr(int_num));
  2225.    end;
  2226.   end;
  2227. end;
  2228.  
  2229. procedure jump(n,o:integer; var inc_ip:boolean);
  2230. var
  2231.  i,j,k,l,loc:integer;
  2232. begin
  2233.  with robot[n]^ do
  2234.   begin
  2235.    loc:=find_label(n,get_val(n,ip,o),code[ip].op[max_op] shr (o*4));
  2236.    if (loc>=0) and (loc<=plen) then begin inc_ip:=false; ip:=loc; end
  2237.                                else robot_error(n,2,cstr(loc));
  2238.   end;
  2239. end;
  2240.  
  2241. {FIFI}
  2242. procedure update_debug_bars;
  2243. begin
  2244.  if graphix and (step_mode>0) then with robot[0]^ do
  2245.   begin
  2246.    {debugger window}
  2247.    viewport(480,4,635,410);
  2248.  
  2249.    {armour}
  2250.    setfillstyle(1,robot_color(0));
  2251.    if armor>0 then
  2252.     bar(88,03,87+(armor shr 2),08);
  2253.    setfillstyle(1,8);
  2254.    if armor<100 then
  2255.     bar(88+(armor shr 2),03,111,08);
  2256.  
  2257.    {heat}
  2258.    setfillstyle(1,robot_color(0));
  2259.    if heat>5 then
  2260.     bar(127,03,126+(heat div 20),08);
  2261.    setfillstyle(1,8);
  2262.    if heat<500 then
  2263.     bar(127+(heat div 20),03,151,08);
  2264.   end;
  2265. end;
  2266. {/FIFI}
  2267.  
  2268. {FIFI}
  2269. procedure update_debug_system;
  2270. var
  2271.  i:integer;
  2272. begin
  2273.  if graphix and (step_mode>0) then with robot[0]^ do
  2274.   begin
  2275.    {debugger window}
  2276.    viewport(480,4,635,410);
  2277.    setfillstyle(1,0);
  2278.    {for i:=0 to 6 do
  2279.     begin
  2280.      bar(039,32+(i*10),70,39+(i*10));
  2281.      bar(110,32+(i*10),141,39+(i*10));
  2282.     end;} {Commented out the black bars, and switched to 'textxy' -Bones}
  2283.    setcolor(robot_color(0));
  2284.    textxy(039,32,hex(ram[0])); textxy(110,32,hex(ram[7]));
  2285.    textxy(039,42,hex(ram[1])); textxy(110,42,hex(ram[8]));
  2286.    textxy(039,52,hex(ram[2])); textxy(110,52,hex(ram[9]));
  2287.    textxy(039,62,hex(ram[3])); textxy(110,62,hex(ram[10]));
  2288.    textxy(039,72,hex(ram[4])); textxy(110,72,hex(ram[11]));
  2289.    textxy(039,82,hex(ram[5])); textxy(110,82,hex(ram[12]));
  2290.    textxy(039,92,hex(ram[6])); textxy(110,92,hex(ram[13]));
  2291.   end;
  2292. end;
  2293. {/FIFI}
  2294.  
  2295. {FIFI}
  2296. procedure update_debug_registers;
  2297. var
  2298.  i:integer;
  2299. begin
  2300.  if graphix and (step_mode>0) then with robot[0]^ do
  2301.   begin
  2302.    {debugger window}
  2303.    viewport(480,4,635,410);
  2304.    setfillstyle(1,0);
  2305.    {for i:=0 to 4 do
  2306.     begin
  2307.      bar(039,122+(i*10),70,129+(i*10));
  2308.      bar(110,122+(i*10),141,129+(i*10));
  2309.     end;} {Commented out the black bars, and switched to 'textxy' -Bones}
  2310.    setcolor(robot_color(0));
  2311.    textxy(039,122,hex(ram[65])); textxy(110,122,hex(ram[69]));
  2312.    textxy(039,132,hex(ram[66])); textxy(110,132,hex(ram[70]));
  2313.    textxy(039,142,hex(ram[67]));
  2314.    textxy(039,152,hex(ram[68])); textxy(110,152,hex(ram[71]));
  2315.   end;
  2316. end;
  2317. {/FIFI}
  2318.  
  2319.  
  2320. {FIFI}
  2321. procedure update_debug_flags;
  2322. var
  2323. bin_string:string;
  2324. begin
  2325.  if graphix and (step_mode>0) then with robot[0]^ do
  2326.   begin
  2327.    {debugger window}
  2328.    viewport(480,4,635,410);
  2329.    bin_string:=bin(ram[64]);
  2330.    if bin_string[13]='1' then setcolor(robot_color(0)) else setcolor(robot_color(8));
  2331.    outtextxy(111,172,'Z');
  2332.    if bin_string[14]='1' then setcolor(robot_color(0)) else setcolor(robot_color(8));
  2333.    outtextxy(119,172,'G');
  2334.    if bin_string[15]='1' then setcolor(robot_color(0)) else setcolor(robot_color(8));
  2335.    outtextxy(127,172,'L');
  2336.    if bin_string[16]='1' then setcolor(robot_color(0)) else setcolor(robot_color(8));
  2337.    outtextxy(135,172,'E');
  2338.    {setfillstyle(1,0);
  2339.    bar(015,182,142,189);
  2340.    setcolor(robot_color(0));}
  2341.    {Commented out the black bars, and switched to 'textxy' -Bones}
  2342.    textxy(015,182,bin(ram[64]));
  2343.   end;
  2344. end;
  2345. {/FIFI}
  2346.  
  2347. {FIFI}
  2348. procedure update_debug_memory;
  2349. var
  2350.  i:integer;
  2351. begin
  2352.  if graphix and (step_mode>0) then with robot[0]^ do
  2353.   begin
  2354.    {debugger window}
  2355.    viewport(480,4,635,410);
  2356.    {setfillstyle(1,0);
  2357.    for i:=0 to 9 do
  2358.     bar(091,212+(i*10),123,222+(i*10));}
  2359.     {Commented out the black bars, and switched to 'textxy' -Bones}
  2360.    setcolor(robot_color(0));
  2361.    for i:=0 to 9 do
  2362.     if ((mem_watch+i)>=0) and ((mem_watch+i)<=1023) then
  2363.      begin
  2364.       textxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2365.       textxy(091,212+(10*i),hex(ram[mem_watch+i]));
  2366.      end;
  2367.   end;
  2368. end;
  2369. {/FIFI}
  2370.  
  2371. {FIFI}
  2372. procedure update_debug_code;
  2373. var
  2374.  i:integer;
  2375. begin
  2376.  if graphix and (step_mode>0) then with robot[0]^ do
  2377.   begin
  2378.    {debugger window}
  2379.    viewport(480,4,635,410);
  2380.    {code}
  2381.    {setfillstyle(1,0);
  2382.    for i:=0 to 6 do bar(003,332+(i*10),152,340+(i*10));}
  2383.    {Commented out the black bars, and switched to 'textxy' -Bones}
  2384.    setcolor(7);
  2385.    for i:=0 to 6 do
  2386.     if (ip+i-3)>=0 then
  2387.      begin
  2388.       if i=3 then setcolor(robot_color(0));
  2389.       textxy(003,332+(i*10),decimal(ip+i-3,4)+': '
  2390.             +mnemonic(code[ip+i-3].op[0],code[ip+i-3].op[3] and 15)+' '
  2391.             +operand(code[ip+i-3].op[1],(code[ip+i-3].op[3] shr 4) and 15)+','
  2392.             +operand(code[ip+i-3].op[2],(code[ip+i-3].op[3] shr 8) and 15));
  2393.       if i=3 then setcolor(7);
  2394.      end;
  2395.   end;
  2396. end;
  2397. {/FIFI}
  2398.  
  2399.  
  2400. {FIFI}
  2401. procedure update_debug_window;
  2402. begin
  2403.  if graphix and (step_mode>0) then
  2404.   begin
  2405.  
  2406.    {armour + heat}
  2407.    update_debug_bars;
  2408.  
  2409.    {system variables}
  2410.    update_debug_system;
  2411.  
  2412.    {registers}
  2413.    update_debug_registers;
  2414.  
  2415.    {flag register}
  2416.    update_debug_flags;
  2417.  
  2418.    {memory}
  2419.    update_debug_memory;
  2420.  
  2421.    {code}
  2422.    update_debug_code;
  2423.  
  2424.   end;
  2425. end;
  2426. {/FIFI}
  2427.  
  2428. {FIFI}
  2429. procedure init_debug_window;
  2430. var i:integer;
  2431. begin
  2432.  if graphix then
  2433.  begin
  2434.  
  2435.  {debugger window}
  2436.  viewport(480,4,635,430);
  2437.  setfillstyle(1,7);
  2438.  bar(0,0,155,422);
  2439.  viewport(480,4,635,410);
  2440.  hole(0,0,155,402);
  2441.  
  2442.  with robot[0]^ do
  2443.   begin
  2444.    setcolor(robot_color(0));
  2445.    outtextxy(003,02,base_name(no_path(fn)));
  2446.  
  2447.    {armour}
  2448.    outtextxy(080,02,'A');
  2449.    setfillstyle(1,robot_color(0));
  2450.  
  2451.    {heat}
  2452.    outtextxy(118,02,'H');
  2453.    setfillstyle(1,robot_color(0));
  2454.  
  2455.    {system variables}
  2456.    setcolor(robot_color(8));
  2457.    outtextxy(007,22,'System:');
  2458.    setcolor(robot_color(0));
  2459.    outtextxy(015,32,'00:      07:');
  2460.    outtextxy(015,42,'01:      08:');
  2461.    outtextxy(015,52,'02:      09:');
  2462.    outtextxy(015,62,'03:      10:');
  2463.    outtextxy(015,72,'04:      11:');
  2464.    outtextxy(015,82,'05:      12:');
  2465.    outtextxy(015,92,'06:      13:');
  2466.  
  2467.    {registers}
  2468.    setcolor(robot_color(8));
  2469.    outtextxy(007,112,'Registers:');
  2470.    setcolor(robot_color(0));
  2471.    outtextxy(015,122,'ax:      ex:');
  2472.    outtextxy(015,132,'bx:      fx:');
  2473.    outtextxy(015,142,'cx:');
  2474.    outtextxy(015,152,'dx:      sp:');
  2475.  
  2476.    {flag register}
  2477.    setcolor(robot_color(8));
  2478.    outtextxy(007,172,'Flags:');
  2479.  
  2480.    {memory}
  2481.    setcolor(robot_color(8));
  2482.    outtextxy(007,202,'Memory:');
  2483.    setcolor(7);
  2484.    outtextxy(103,202,'-+,[]');
  2485.    setcolor(robot_color(0));
  2486.    for i:=0 to 9 do
  2487.     outtextxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2488.  
  2489.    {code}
  2490.    setcolor(robot_color(8));
  2491.    outtextxy(007,322,'Code:');
  2492.  
  2493.   end;
  2494.  update_debug_window;
  2495.  
  2496.  end;
  2497. end;
  2498. {/FIFI}
  2499.  
  2500. {FIFI}
  2501. procedure close_debug_window;
  2502. var i:integer;
  2503. begin
  2504.  if graphix then
  2505.  begin
  2506.  
  2507.  stats_mode:=0;
  2508.  case num_robots of
  2509.   0..5:stats_mode:=0;
  2510.   6..11:stats_mode:=1;
  2511.   12..max_robots:stats_mode:=2;
  2512.   else stats_mode:=0;
  2513.  end;
  2514.  
  2515.  viewport(480,4,635,430);
  2516.  setfillstyle(1,7);
  2517.  bar(0,0,155,426);
  2518. { update_cycle_window;}
  2519.  
  2520.  {--robot windows--}
  2521.  for i:=0 to max_robots do
  2522.   if i<max_shown then with robot[i]^ do
  2523.    begin
  2524.     robot_graph(i);
  2525.     hole(0,0,max_gx,max_gy);
  2526.     if i<=num_robots then
  2527.      begin
  2528.       setcolor(robot_color(i));
  2529.       outtextxy(003,02,base_name(no_path(fn)));
  2530.       case stats_mode of
  2531.        1:begin
  2532.           outtextxy(003,12,' A:');
  2533.           outtextxy(003,22,' H:');
  2534.          end;
  2535.        2:begin
  2536.           setcolor(robot_color(i) and 7);
  2537.           outtextxy(080,02,'A');
  2538.           outtextxy(118,02,'H');
  2539.          end;
  2540.        else begin
  2541.           outtextxy(003,24,' A:');
  2542.           outtextxy(003,34,' H:');
  2543.          end;
  2544.       end;
  2545.       setcolor(robot_color(i));
  2546.       if stats_mode<=1 then
  2547.        begin
  2548.         outtextxy(080,02,'Wins:');
  2549.         outtextxy(122,02,zero_pad(wins,4));
  2550.        end;
  2551.       if stats_mode=0 then
  2552.        begin
  2553.         outtextxy(003,56,' Error:');
  2554.         setcolor(robot_color(i) and 7);
  2555.         outtextxy(003,12,name);
  2556.         setcolor(8);
  2557.         outtextxy(66,56,'None');
  2558.        end;
  2559.       lx:=1000-x; ly:=1000-y;
  2560.       update_armor(i);
  2561.       update_heat(i);
  2562.       update_lives(i);
  2563.      end
  2564.     else
  2565.      begin
  2566.       setfillpattern(gray50,8);
  2567.       bar(1,1,max_gx-1,max_gy-1);
  2568.      end;
  2569.    end;
  2570.  
  2571.  end;
  2572. end;
  2573. {/FIFI}
  2574.  
  2575. function gameover:boolean;
  2576. var
  2577.  n,i,j,k,l:integer;
  2578. begin
  2579.  if (game_cycle>=game_limit) and (game_limit>0) then
  2580.      begin gameover:=true; exit; end;
  2581.  if game_cycle and 31=0 then
  2582.   begin
  2583.    k:=0;
  2584.    for n:=0 to num_robots do
  2585.     if robot[n]^.armor>0 then inc(k);
  2586.    if k<=1 then gameover:=true
  2587.            else gameover:=false;
  2588.   end else gameover:=false;
  2589. end;
  2590.  
  2591. procedure toggle_graphix;
  2592. begin
  2593.  graph_mode(not graphix);
  2594.  if not graphix then
  2595.   begin
  2596.    textcolor(7);
  2597.    writeln('Match ',played,'/',matches,', Battle in progress...');
  2598.    writeln;
  2599.   end
  2600.  else setscreen;
  2601. end;
  2602.  
  2603. function invalid_microcode(n,ip:integer):boolean;
  2604. var
  2605.  invalid:boolean;
  2606.  i,j,k:integer;
  2607. begin
  2608.  invalid:=false;
  2609.  for i:=0 to 2 do
  2610.   begin
  2611.    k:=(robot[n]^.code[ip].op[max_op] shr (i shl 2)) and 7;
  2612.    if not (k in [0,1,2,4]) then invalid:=true;
  2613.   end;
  2614.  invalid_microcode:=invalid;
  2615. end;
  2616.  
  2617. procedure process_keypress(c:char);
  2618. begin
  2619.  case c of
  2620.    'C':calibrate_timing;
  2621.    'T':timing:=not timing;
  2622.    'A':show_arcs:=not show_arcs;
  2623.    'S','Q':begin
  2624.             if sound_on then chirp;
  2625.             sound_on:=not sound_on;
  2626.             if sound_on then chirp;
  2627.            end;
  2628.    '$':debug_info:=not debug_info;
  2629.    'W':windoze:=not windoze;
  2630.     #8:bout_over:=true;
  2631.    #27:begin quit:=true; step_loop:=false; end;
  2632.  end;
  2633. end;
  2634.  
  2635. procedure execute_instruction(n:integer);
  2636. var
  2637.  i,j,k:integer;
  2638.  time_used,loc:integer;
  2639.  inc_ip:boolean;
  2640.  {FIFI}
  2641.  c:char;
  2642.  {/FIFI}
  2643. begin
  2644.  with robot[n]^ do
  2645.   begin
  2646.    {--update system variables--}
  2647.    ram[000]:=tspd;
  2648.    ram[001]:=thd;
  2649.    ram[002]:=shift;
  2650.    ram[003]:=accuracy;
  2651.  
  2652.    time_used:=1; inc_ip:=true; loc:=0;
  2653.    if (ip>plen) or (ip<0) then ip:=0;
  2654.    if invalid_microcode(n,ip) then
  2655.       begin time_used:=1; robot_error(n,16,hex(code[ip].op[max_op])); end
  2656.     else
  2657.  
  2658.   {FIFI}
  2659.   if graphix and (step_mode>0) and (n=0) then  {if stepping enabled...}
  2660.    begin
  2661.     inc(step_count);
  2662.     update_cycle_window;
  2663.     update_debug_window;
  2664.     if (step_count mod step_mode)=0 then step_loop:=true else step_loop:=false;
  2665.     while step_loop and (not(quit or gameover or bout_over)) do
  2666.      if keypressed then with robot[0]^ do
  2667.       begin
  2668.        c:=upcase(readkey);
  2669.        case c of
  2670.         'X':begin
  2671.              temp_mode:=step_mode;
  2672.              step_mode:=0;
  2673.              step_loop:=false;
  2674.              close_debug_window;
  2675.             end;
  2676.         ' ':begin step_count:=0; step_loop:=false; end;
  2677.         '1'..'9':begin step_mode:=value(c); step_count:=0; step_loop:=false; end;
  2678.         '0':begin step_mode:=10; step_count:=0; step_loop:=false; end;
  2679.         '-','_':if mem_watch>0 then
  2680.                  begin
  2681.                   setcolor(0);
  2682.                   for i:=0 to 9 do
  2683.                    outtextxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2684.                   dec(mem_watch);
  2685.                   update_debug_memory;
  2686.                  end;
  2687.         '+','=':if mem_watch<1014 then
  2688.                  begin
  2689.                   setcolor(0);
  2690.                   for i:=0 to 9 do
  2691.                    outtextxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2692.                   inc(mem_watch);
  2693.                   update_debug_memory;
  2694.                  end;
  2695.         '[','{':if mem_watch>0 then
  2696.                  begin
  2697.                   setcolor(0);
  2698.                   for i:=0 to 9 do
  2699.                    outtextxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2700.                   dec(mem_watch,10);
  2701.                   if mem_watch<0 then mem_watch:=0;
  2702.                   update_debug_memory;
  2703.                  end;
  2704.         ']','}':if mem_watch<1014 then
  2705.                  begin
  2706.                   setcolor(0);
  2707.                   for i:=0 to 9 do
  2708.                    outtextxy(035,212+(10*i),decimal((mem_watch+i),4) + ' :');
  2709.                   inc(mem_watch,10);
  2710.                   if mem_watch>1014 then mem_watch:=1014;
  2711.                   update_debug_memory;
  2712.                  end;
  2713.         'G':begin toggle_graphix; temp_mode:=step_mode; step_mode:=0; step_loop:=false; end;
  2714.         else process_keypress(c);
  2715.        end;
  2716.       end;
  2717.    end;
  2718.   {/FIFI}
  2719.  
  2720.    if (not ((code[ip].op[max_op] and 7) in [0,1])) then
  2721.       begin time_used:=0; end
  2722.     else
  2723.    case get_val(n,ip,0) of
  2724.     00:begin (*NOP*)
  2725.         inc(executed);
  2726.        end;
  2727.     01:begin (*ADD*)
  2728.         put_val(n,ip,1,get_val(n,ip,1)+get_val(n,ip,2));
  2729.         inc(executed);
  2730.        end;
  2731.     02:begin (*SUB*)
  2732.         put_val(n,ip,1,get_val(n,ip,1)-get_val(n,ip,2));
  2733.         inc(executed);
  2734.        end;
  2735.     03:begin (*OR*)
  2736.         put_val(n,ip,1,get_val(n,ip,1) or get_val(n,ip,2));
  2737.         inc(executed);
  2738.        end;
  2739.     04:begin (*AND*)
  2740.         put_val(n,ip,1,get_val(n,ip,1) and get_val(n,ip,2));
  2741.         inc(executed);
  2742.        end;
  2743.     05:begin (*XOR*)
  2744.         put_val(n,ip,1,get_val(n,ip,1) xor get_val(n,ip,2));
  2745.         inc(executed);
  2746.        end;
  2747.     06:begin (*NOT*)
  2748.         put_val(n,ip,1,not(get_val(n,ip,1)));
  2749.         inc(executed);
  2750.        end;
  2751.     07:begin (*MPY*)
  2752.         put_val(n,ip,1,get_val(n,ip,1)*get_val(n,ip,2));
  2753.         time_used:=10;
  2754.         inc(executed);
  2755.        end;
  2756.     08:begin (*DIV*)
  2757.         j:=get_val(n,ip,2);
  2758.         if j<>0 then put_val(n,ip,1,get_val(n,ip,1) div j)
  2759.                 else robot_error(n,8,'');
  2760.         time_used:=10;
  2761.         inc(executed);
  2762.        end;
  2763.     09:begin (*MOD*)
  2764.         j:=get_val(n,ip,2);
  2765.         if j<>0 then put_val(n,ip,1,get_val(n,ip,1) mod j)
  2766.                 else robot_error(n,8,'');
  2767.         time_used:=10;
  2768.         inc(executed);
  2769.        end;
  2770.     10:begin (*RET*)
  2771.         ip:=pop(n);
  2772.         if (ip<0) or (ip>plen) then robot_error(n,7,cstr(ip));
  2773.         inc(executed);
  2774.        end;
  2775.     11:begin (*GSB*)
  2776.         loc:=find_label(n,get_val(n,ip,1),code[ip].op[max_op] shr (1*4));
  2777.         if loc>=0 then begin push(n,ip); inc_ip:=false; ip:=loc; end
  2778.                   else robot_error(n,2,cstr(get_val(n,ip,1)));
  2779.         inc(executed);
  2780.        end;
  2781.     12:begin (*JMP*)
  2782.         jump(n,1,inc_ip);
  2783.         inc(executed);
  2784.        end;
  2785.     13:begin (*JLS,JB*)
  2786.         if ram[64] and 2>0 then
  2787.            jump(n,1,inc_ip);
  2788.         time_used:=0;
  2789.         inc(executed);
  2790.        end;
  2791.     14:begin (*JGR,JA*)
  2792.         if ram[64] and 4>0 then
  2793.            jump(n,1,inc_ip);
  2794.         time_used:=0;
  2795.         inc(executed);
  2796.        end;
  2797.     15:begin (*JNE*)
  2798.         if ram[64] and 1=0 then
  2799.            jump(n,1,inc_ip);
  2800.         time_used:=0;
  2801.         inc(executed);
  2802.        end;
  2803.     16:begin (*JEQ,JE*)
  2804.         if ram[64] and 1>0 then
  2805.            jump(n,1,inc_ip);
  2806.         time_used:=0;
  2807.         inc(executed);
  2808.        end;
  2809.     17:begin (*SWAP, XCHG*)
  2810.         ram[4]:=get_val(n,ip,1);
  2811.         put_val(n,ip,1,get_val(n,ip,2));
  2812.         put_val(n,ip,2,ram[4]);
  2813.         time_used:=3;
  2814.         inc(executed);
  2815.        end;
  2816.     18:begin (*DO*)
  2817.         ram[67]:=get_val(n,ip,1);
  2818.         inc(executed);
  2819.        end;
  2820.     19:begin (*LOOP*)
  2821.         dec(ram[67]);
  2822.         if ram[67]>0 then
  2823.            jump(n,1,inc_ip);
  2824.         inc(executed);
  2825.        end;
  2826.     20:begin (*CMP*)
  2827.         k:=get_val(n,ip,1)-get_val(n,ip,2);
  2828.         ram[64]:=ram[64] and $FFF0;
  2829.         if k=0 then ram[64]:=ram[64] or 1;
  2830.         if k<0 then ram[64]:=ram[64] or 2;
  2831.         if k>0 then ram[64]:=ram[64] or 4;
  2832.         if (get_val(n,ip,2)=0) and (k=0) then
  2833.                     ram[64]:=ram[64] or 8;
  2834.         inc(executed);
  2835.        end;
  2836.     21:begin (*TEST*)
  2837.         k:=get_val(n,ip,1) and get_val(n,ip,2);
  2838.         ram[64]:=ram[64] and $FFF0;
  2839.         if k=get_val(n,ip,2) then ram[64]:=ram[64] or 1;
  2840.         if k=0               then ram[64]:=ram[64] or 8;
  2841.         inc(executed);
  2842.        end;
  2843.     22:begin (*MOV, SET*)
  2844.         put_val(n,ip,1,get_val(n,ip,2));
  2845.         inc(executed);
  2846.        end;
  2847.     23:begin (*LOC*)
  2848.         put_val(n,ip,1,code[ip].op[2]);
  2849.         time_used:=2;
  2850.         inc(executed);
  2851.        end;
  2852.     24:begin (*GET*)
  2853.         k:=get_val(n,ip,2);
  2854.         if (k>=0) and (k<=max_ram) then
  2855.             put_val(n,ip,1,ram[k])
  2856.           else if (k>max_ram) and (k<=(Max_ram+1)+(((max_code+1) shl 3)-1)) then
  2857.            begin
  2858.             j:=k-max_ram-1;
  2859.             put_val(n,ip,1,code[j shr 2].op[j and 3]);
  2860.            end
  2861.           else robot_error(n,4,cstr(k));
  2862.         time_used:=2;
  2863.         inc(executed);
  2864.        end;
  2865.     25:begin (*PUT*)
  2866.         k:=get_val(n,ip,2);
  2867.         if (k>=0) and (k<=max_ram) then
  2868.             ram[k]:=get_val(n,ip,1)
  2869.           else robot_error(n,4,cstr(k));
  2870.         time_used:=2;
  2871.         inc(executed);
  2872.        end;
  2873.     26:begin (*INT*)
  2874.         call_int(n,get_val(n,ip,1),time_used);
  2875.         inc(executed);
  2876.        end;
  2877.     27:begin (*IPO,IN*)
  2878.         time_used:=4;
  2879.         put_val(n,ip,2,in_port(n,get_val(n,ip,1),time_used));
  2880.         inc(executed);
  2881.        end;
  2882.     28:begin (*OPO,OUT*)
  2883.         time_used:=4;
  2884.         out_port(n,get_val(n,ip,1),get_val(n,ip,2),time_used);
  2885.         inc(executed);
  2886.        end;
  2887.     29:begin (*DEL,DELAY*)
  2888.         time_used:=get_val(n,ip,1);
  2889.         inc(executed);
  2890.        end;
  2891.     30:begin (*PUSH*)
  2892.         push(n,get_val(n,ip,1));
  2893.         inc(executed);
  2894.        end;
  2895.     31:begin (*POP*)
  2896.         put_val(n,ip,1,pop(n));
  2897.         inc(executed);
  2898.        end;
  2899.     32:begin (*ERR*)
  2900.         robot_error(n,get_val(n,ip,1),'');
  2901.         time_used:=0;
  2902.         inc(executed);
  2903.        end;
  2904.     33:begin (*INC*)
  2905.         put_val(n,ip,1,get_val(n,ip,1)+1);
  2906.         inc(executed);
  2907.        end;
  2908.     34:begin (*DEC*)
  2909.         put_val(n,ip,1,get_val(n,ip,1)-1);
  2910.         inc(executed);
  2911.        end;
  2912.     35:begin (*SHL*)
  2913.         put_val(n,ip,1,get_val(n,ip,1) shl get_val(n,ip,2));
  2914.         inc(executed);
  2915.        end;
  2916.     36:begin (*SHR*)
  2917.         put_val(n,ip,1,get_val(n,ip,1) shr get_val(n,ip,2));
  2918.         inc(executed);
  2919.        end;
  2920.     37:begin (*ROL*)
  2921.         put_val(n,ip,1,rol(get_val(n,ip,1),get_val(n,ip,2)));
  2922.         inc(executed);
  2923.        end;
  2924.     38:begin (*ROR*)
  2925.         put_val(n,ip,1,ror(get_val(n,ip,1),get_val(n,ip,2)));
  2926.         inc(executed);
  2927.        end;
  2928.     39:begin (*JZ*)
  2929.         time_used:=0;
  2930.         if ram[64] and 8>0 then
  2931.            jump(n,1,inc_ip);
  2932.         inc(executed);
  2933.        end;
  2934.     40:begin (*JNZ*)
  2935.         time_used:=0;
  2936.         if ram[64] and 8=0 then
  2937.            jump(n,1,inc_ip);
  2938.         inc(executed);
  2939.        end;
  2940.     41:begin (*JAE,JGE*)
  2941.         if (ram[64] and 1>0) or (ram[64] and 4>0) then
  2942.            jump(n,1,inc_ip);
  2943.         time_used:=0;
  2944.         inc(executed);
  2945.        end;
  2946.     42:begin (*JBE,JLE*)
  2947.         if (ram[64] and 1>0) or (ram[64] and 2>0) then
  2948.            jump(n,1,inc_ip);
  2949.         time_used:=0;
  2950.         inc(executed);
  2951.        end;
  2952.     43:begin (*SAL*)
  2953.         put_val(n,ip,1,sal(get_val(n,ip,1),get_val(n,ip,2)));
  2954.         inc(executed);
  2955.        end;
  2956.     44:begin (*SAR*)
  2957.         put_val(n,ip,1,sar(get_val(n,ip,1),get_val(n,ip,2)));
  2958.         inc(executed);
  2959.        end;
  2960.     45:begin (*NEG*)
  2961.         put_val(n,ip,1,0-get_val(n,ip,1));
  2962.         inc(executed);
  2963.        end;
  2964.     46:begin (*JTL*)
  2965.         loc:=get_val(n,ip,1);
  2966.         if (loc>=0) and (loc<=plen) then begin inc_ip:=false; ip:=loc; end
  2967.                                     else robot_error(n,2,cstr(loc));
  2968.        end;
  2969.     else begin robot_error(n,6,''); end;
  2970.    end;
  2971.    inc(delay_left,time_used);
  2972.    if inc_ip then inc(ip);
  2973.    {FIFI}
  2974.    if graphix and (n=0) and (step_mode>0) then update_debug_window;
  2975.    {/FIFI}
  2976.   end;
  2977. end;
  2978.  
  2979. procedure do_robot(n:integer);
  2980. var
  2981.  i,j,k,l,tthd:integer;
  2982.  heat_mult,ttx,tty:real;
  2983. begin
  2984.  if (n<0) or (n>num_robots) then exit;
  2985.  with robot[n]^ do
  2986.   begin
  2987.    if armor<=0 then exit;
  2988.  
  2989.    {--time slice--}
  2990.    time_left:=time_slice;
  2991.    if (time_left>robot_time_limit) and (robot_time_limit>0) then
  2992.       time_left:=robot_time_limit;
  2993.    if (time_left>max_time) and (max_time>0) then time_left:=max_time;
  2994.    executed:=0;
  2995.  
  2996.    {--execute timeslice--}
  2997.     while (time_left>0) and (not cooling) and (executed<20+time_slice) and (armor>0) do
  2998.      begin
  2999.       if delay_left<0 then delay_left:=0;
  3000.       if (delay_left>0) then begin dec(delay_left); dec(time_left); end;
  3001.       if (time_left>=0) and (delay_left=0) then
  3002.         execute_instruction(n);
  3003.       if heat>=shutdown then begin cooling:=true; shields_up:=false; end;
  3004.       if heat>=500 then damage(n,1000,true);
  3005.      end;
  3006.  
  3007.    {--fix up variables--}
  3008.    thd:=(thd+1024) and 255;
  3009.    hd:=(hd+1024) and 255;
  3010.    shift:=(shift+1024) and 255;
  3011.    if tspd<-75 then tspd:=-75;
  3012.    if tspd>100 then tspd:=100;
  3013.    if spd<-75 then spd:=-75;
  3014.    if spd>100 then spd:=100;
  3015.    if heat<0 then heat:=0;
  3016.    if last_damage<maxint then inc(last_damage);
  3017.    if last_hit<maxint then inc(last_hit);
  3018.  
  3019.    {--update heat--}
  3020.    if shields_up and (game_cycle and 3=0) then inc(heat);
  3021.    if not shields_up then
  3022.     begin
  3023.      if heat>0 then
  3024.       case config.heatsinks of  (*heat adjustments*)
  3025.        5:if game_cycle and 1=0 then dec(heat);
  3026.        4:if game_cycle mod 3=0 then dec(heat);
  3027.        3:if game_cycle and 3=0 then dec(heat);
  3028.        2:if game_cycle and 7=0 then dec(heat);
  3029.        1:begin (*Do nothing, no adjustment needed*) end;
  3030.        else if game_cycle and 3=0 then inc(heat);
  3031.       end;
  3032.      if overburn and (game_cycle mod 3=0) then inc(heat);
  3033.      if (heat>0) then dec(heat);
  3034.      if (heat>0) and (game_cycle and 7=0) and (abs(tspd)<=25) then dec(heat);
  3035.      if (heat<=shutdown-50) or (heat<=0) then cooling:=false;
  3036.     end;
  3037.    if cooling then begin tspd:=0; end;
  3038.    heat_mult:=1;
  3039.    case heat of
  3040.     080..099:heat_mult:=0.98;
  3041.     100..149:heat_mult:=0.95;
  3042.     150..199:heat_mult:=0.85;
  3043.     200..249:heat_mult:=0.75;
  3044.     250..maxint:heat_mult:=0.50;
  3045.    end;
  3046.    if overburn then heat_mult:=heat_mult*1.30;
  3047.    if (heat>=475) and (game_cycle and 03=0) then damage(n,1,true) else
  3048.    if (heat>=450) and (game_cycle and 07=0) then damage(n,1,true) else
  3049.    if (heat>=400) and (game_cycle and 15=0) then damage(n,1,true) else
  3050.    if (heat>=350) and (game_cycle and 31=0) then damage(n,1,true) else
  3051.    if (heat>=300) and (game_cycle and 63=0) then damage(n,1,true);
  3052.  
  3053.    {--update robot in physical world--}
  3054.    {-acceleration-}
  3055.    if abs(spd-tspd)<=acceleration then spd:=tspd
  3056.       else begin
  3057.             if tspd>spd then inc(spd,acceleration)
  3058.                         else dec(spd,acceleration);
  3059.            end;
  3060.    {-turning-}
  3061.    tthd:=hd+shift;
  3062.    if (abs(hd-thd)<=turn_rate) or (abs(hd-thd)>=256-turn_rate) then
  3063.       hd:=thd
  3064.     else if hd<>thd then
  3065.      begin
  3066.       k:=0;
  3067.       if ((thd>hd) and (abs(hd-thd)<=128)) or
  3068.          ((thd<hd) and (abs(hd-thd)>=128)) then k:=1;
  3069.       if k=1 then hd:=(hd+turn_rate) and 255
  3070.              else hd:=(hd+256-turn_rate) and 255;
  3071.      end;
  3072.    hd:=hd and 255;
  3073.    if keepshift then shift:=(tthd-hd+1024) and 255;
  3074.    {-moving-}
  3075.    speed:=spd/100*(max_vel*heat_mult*speedadj);
  3076.    xv:= sint[hd]*speed;
  3077.    yv:=-cost[hd]*speed;
  3078.    if (hd=0) or (hd=128) then xv:=0;
  3079.    if (hd=64) or (hd=192) then yv:=0;
  3080.    if xv<>0 then ttx:=x+xv else ttx:=x;
  3081.    if yv<>0 then tty:=y+yv else tty:=y;
  3082.    if (ttx<0) or (tty<0) or (ttx>1000) or (tty>1000) then
  3083.       begin inc(ram[8]); tspd:=0; if abs(speed)>=max_vel/2 then damage(n,1,true); spd:=0; {ttx:=x; tty:=y;} end;
  3084.    for i:=0 to num_robots do
  3085.     if (i<>n) and (robot[i]^.armor>0) and (distance(ttx,tty,robot[i]^.x,robot[i]^.y)<crash_range)
  3086.        then begin
  3087.              tspd:=0; spd:=0; ttx:=x; tty:=y;
  3088.              robot[i]^.tspd:=0; robot[i]^.spd:=0;
  3089.              inc(ram[8]); inc(robot[i]^.ram[8]);
  3090.              if abs(speed)>=max_vel/2 then begin damage(n,1,true); damage(i,1,true); end;
  3091.             end;
  3092.    if ttx<0 then ttx:=0;
  3093.    if tty<0 then tty:=0;
  3094.    if ttx>1000 then ttx:=1000;
  3095.    if tty>1000 then tty:=1000;
  3096.    meters:=meters+distance(x,y,ttx,tty);
  3097.    if meters>=maxint then meters:=meters-maxint;
  3098.    ram[9]:=trunc(meters);
  3099.    x:=ttx; y:=tty;
  3100.  
  3101.  
  3102.    {--draw robot--}
  3103.    if armor<0 then armor:=0;
  3104.    if heat<0 then heat:=0;
  3105.    if graphix then
  3106.     begin
  3107.      if armor<>larmor then update_armor(n);
  3108.      if heat div 5<>lheat div 5 then update_heat(n);
  3109.      draw_robot(n);
  3110.     end;
  3111.    lheat:=heat; larmor:=armor;
  3112.  
  3113.    {--Cycle complete, inc counter--}
  3114.    inc(cycles_lived);
  3115.   end;
  3116. end;
  3117.  
  3118. procedure do_mine(n,m:integer);
  3119. var
  3120.  i,j,k,l:integer;
  3121.  d,r:real;
  3122.  source_alive:boolean;
  3123. begin
  3124.  with robot[n]^.mine[m] do
  3125.   if (x>=0) and (x<=1000) and (y>=0) and (y<=1000) and (yield>0) then
  3126.    begin
  3127.     for i:=0 to num_robots do
  3128.      if (robot[i]^.armor>0) and (i<>n) then
  3129.       begin
  3130.        d:=distance(x,y,robot[i]^.x,robot[i]^.y);
  3131.        if d<=detect then detonate:=true;
  3132.       end;
  3133.     if detonate then
  3134.      begin
  3135.       init_missile(x,y,0,0,0,n,mine_circle,false);
  3136.       kill_count:=0;
  3137.       if (robot[n]^.armor>0) then source_alive:=true else source_alive:=false;
  3138.       for i:=0 to num_robots do
  3139.        if {(i<>n) and} (robot[i]^.armor>0) then
  3140.         begin
  3141.          k:=round(distance(x,y,robot[i]^.x,robot[i]^.y));
  3142.          if k<yield then
  3143.           begin
  3144.            damage(i,round(abs(yield-k)),false);
  3145.            if (n in [0..num_robots]) and (i<>n) then
  3146.               inc(robot[n]^.damage_total,round(abs(yield-k)));
  3147.           end;
  3148.         end;
  3149.        if (kill_count>0) and (source_alive) and (robot[n]^.armor<=0) then dec(kill_count);
  3150.        if kill_count>0 then
  3151.         begin
  3152.          inc(robot[n]^.kills,kill_count);
  3153.          update_lives(n);
  3154.         end;
  3155.       if graphix then
  3156.        putpixel(round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y,0);
  3157.       yield:=0; x:=-1; y:=-1;
  3158.      end
  3159.     else
  3160.      begin
  3161.       (* Draw mine *)
  3162.       if graphix and (game_cycle and 1=0) then
  3163.        begin
  3164.         main_viewport;
  3165.         setcolor(robot_color(n));
  3166.         line(round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y-1,
  3167.              round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y+1);
  3168.         line(round(x*screen_scale)+screen_x+1,round(y*screen_scale)+screen_y,
  3169.              round(x*screen_scale)+screen_x-1,round(y*screen_scale)+screen_y);
  3170.        end;
  3171.      end;
  3172.    end;
  3173. end;
  3174.  
  3175. procedure do_missile(n:integer);
  3176. var
  3177.  llx,lly,r,d,dir,xv,yv:real;
  3178.  i,j,k,l,xx,yy,tx,ty,dd,dam:integer;
  3179.  source_alive:boolean;
  3180. begin
  3181.  with missile[n] do
  3182.   if a=0 then exit else
  3183.   begin
  3184.    if a=1 then
  3185.     begin
  3186.      {--Look for collision w/ wall--}
  3187.      if (x<-20) or (x>1020) or (y<-20) or (y>1020) then a:=0;
  3188.  
  3189.      {--move missile--}
  3190.      llx:=lx; lly:=ly;
  3191.      lx:=x; ly:=y;
  3192.      if a>0 then
  3193.       begin
  3194.        hd:=(hd+256) and 255;
  3195.        xv:= sint[hd]*mspd;
  3196.        yv:=-cost[hd]*mspd;
  3197.        x:=x+xv;
  3198.        y:=y+yv;
  3199.       end;
  3200.  
  3201.      {--look for hit on a robot--}
  3202.      k:=-1; l:=maxint;
  3203.      for i:=0 to num_robots do
  3204.       if (robot[i]^.armor>0) and (i<>source) then
  3205.        begin
  3206.         d:=distance(lx,ly,robot[i]^.x,robot[i]^.y);
  3207.         {dir:=find_angle(lx,ly,robot[i]^.x,robot[i]^.y);
  3208.         j:=(round(dir/pi*128)+1024) and 255;}
  3209.         hd:=hd and 255;
  3210.         xx:=round( sint[hd]*d+lx);
  3211.         yy:=round(-cost[hd]*d+ly);
  3212.         r:=distance(xx,yy,robot[i]^.x,robot[i]^.y);
  3213.         if (d<=mspd) and (r<hit_range) and (round(d)<=l) then
  3214.          begin k:=i; l:=round(d); dd:=round(r); tx:=xx; ty:=yy; end;
  3215.        end;
  3216.      if k>=0 then  (*hit a robot!*)
  3217.       begin
  3218.        x:=tx; y:=ty; a:=2; rad:=0; lrad:=0;
  3219.        if source in [0..num_robots] then
  3220.         begin
  3221.          robot[source]^.last_hit:=0;
  3222.          inc(robot[source]^.hits);
  3223.         end;
  3224.        for i:=0 to num_robots do
  3225.         begin
  3226.          dd:=round(distance(x,y,robot[i]^.x,robot[i]^.y));
  3227.          if dd<=hit_range then
  3228.            begin
  3229.             dam:=round(abs(hit_range-dd)*mult);
  3230.             if dam<=0 then dam:=1;
  3231.             kill_count:=0;
  3232.             if (robot[source]^.armor>0) then source_alive:=true else source_alive:=false;
  3233.             damage(i,dam,false);
  3234.             if (source in [0..num_robots]) and (i<>source) then
  3235.               inc(robot[source]^.damage_total,dam);
  3236.             if (kill_count>0) and (source_alive) and (robot[source]^.armor<=0) then dec(kill_count);
  3237.             if kill_count>0 then
  3238.              begin
  3239.               inc(robot[source]^.kills,kill_count);
  3240.               update_lives(source);
  3241.              end;
  3242.            end;
  3243.         end;
  3244.       end;
  3245.  
  3246.      {--draw missile--}
  3247.      if graphix then
  3248.       begin
  3249.        main_viewport;
  3250.        setcolor(0);
  3251.        line(round(llx*screen_scale)+screen_x,round(lly*screen_scale)+screen_y,
  3252.             round(lx*screen_scale)+screen_x,round(ly*screen_scale)+screen_y);
  3253.        if a=1 then
  3254.         begin
  3255.          if mult>robot[source]^.shotstrength then setcolor(14+(game_cycle and 1)) else setcolor(15);
  3256.          line(round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y,
  3257.               round(lx*screen_scale)+screen_x,round(ly*screen_scale)+screen_y);
  3258.         end;
  3259.       end;
  3260.     end;
  3261.    if (a=2) then
  3262.     begin
  3263.      lrad:=rad;
  3264.      inc(rad);
  3265.      if rad>max_rad then a:=0;
  3266.      if graphix then
  3267.       begin
  3268.        main_viewport;
  3269.        setcolor(0);
  3270.        circle(round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y,lrad);
  3271.        if mult>1 then setcolor(14+(game_cycle and 1)) else setcolor(15);
  3272.        if max_rad>=blast_circle then setcolor(14);
  3273.        if max_rad>=mine_circle then setcolor(11);
  3274.        if a>0 then
  3275.         circle(round(x*screen_scale)+screen_x,round(y*screen_scale)+screen_y,rad);
  3276.       end;
  3277.     end;
  3278.   end;
  3279. end;
  3280.  
  3281. function victor_string(k,n:integer):string;
  3282. var
  3283.  s:string;
  3284. begin
  3285.  s:='';
  3286.  if k=1 then s:='Robot #'+cstr(n+1)+' ('+robot[n]^.fn+') wins!';
  3287.  if k=0 then s:='Simultaneous destruction, match is a tie.';
  3288.  if k>1 then s:='No clear victor, match is a tie.';
  3289.  victor_string:=s;
  3290. end;
  3291.  
  3292. procedure show_statistics;
  3293. var
  3294.  i,j,k,n,sx,sy:integer;
  3295. begin
  3296.  if not windoze then exit;
  3297.  if graphix then
  3298.   begin
  3299.    sx:=24; sy:=93-num_robots*3;
  3300.    viewport(0,0,639,479);
  3301.    box(sx+000,sy,sx+591,sy+102+num_robots*12);
  3302.    hole(sx+004,sy+004,sx+587,sy+098+num_robots*12);
  3303.    setfillpattern(gray50,1);
  3304.    bar(sx+005,sy+005,sx+586,sy+097+num_robots*12);
  3305.    setcolor(15);
  3306.    outtextxy(sx+016,sy+020,'Robot            Scored   Wins  Matches  Armor  Kills  Deaths    Shots');
  3307.    outtextxy(sx+016,sy+030,'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
  3308.    n:=-1; k:=0;
  3309.    for i:=0 to num_robots do
  3310.     with robot[i]^ do
  3311.      if (armor>0) or (won) then begin inc(k); n:=i; end;
  3312.    for i:=0 to num_robots do
  3313.     with robot[i]^ do
  3314.      begin
  3315.       setcolor(robot_color(i));
  3316.       if (k=1) and (n=i) then j:=1 else j:=0;
  3317.       outtextxy(sx+016,sy+042+i*12,addfront(cstr(i+1),2)+' - '+addrear(fn,15)+cstr(j)
  3318.                +addfront(cstr(wins),8)+addfront(cstr(trials),8)
  3319.                +addfront(cstr(armor)+'%',9)+addfront(cstr(kills),7)
  3320.                +addfront(cstr(deaths),8)+addfront(cstr(match_shots),9));
  3321.      end;
  3322.    setcolor(15);
  3323.    outtextxy(sx+016,sy+064+num_robots*12,victor_string(k,n));
  3324.    if windoze then
  3325.     begin
  3326.      outtextxy(sx+016,sy+076+num_robots*12,'Press any key to continue...');
  3327.      flushkey; readkey;
  3328.     end;
  3329.   end
  3330.  else
  3331.   begin
  3332.    textcolor(15);
  3333.    write(#13+space(79)+#13);
  3334.    writeln('Match ',played,'/',matches,' results:');
  3335.    writeln;
  3336.    writeln('Robot            Scored   Wins  Matches  Armor  Kills  Deaths    Shots');
  3337.    writeln('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
  3338.    n:=-1; k:=0;
  3339.    for i:=0 to num_robots do
  3340.     with robot[i]^ do
  3341.      if (armor>0) or (won) then begin inc(k); n:=i; end;
  3342.    for i:=0 to num_robots do
  3343.     with robot[i]^ do
  3344.      begin
  3345.       textcolor(robot_color(i));
  3346.       if (k=1) and (n=i) then j:=1 else j:=0;
  3347.       writeln(addfront(cstr(i+1),2)+' - '+addrear(fn,15)+cstr(j)
  3348.              +addfront(cstr(wins),8)+addfront(cstr(trials),8)
  3349.              +addfront(cstr(armor)+'%',9)+addfront(cstr(kills),7)
  3350.              +addfront(cstr(deaths),8)+addfront(cstr(match_shots),9));
  3351.      end;
  3352.    textcolor(15);
  3353.    writeln;
  3354.    writeln(victor_string(k,n));
  3355.    writeln;
  3356.    {writeln('Press any key to continue...'); readkey;}
  3357.   end;
  3358. end;
  3359.  
  3360. procedure score_robots;
  3361. var
  3362.  n,i,j,k,l:integer;
  3363. begin
  3364.  k:=0; n:=-1;
  3365.  for i:=0 to num_robots do
  3366.   begin
  3367.    inc(robot[i]^.trials);
  3368.    if robot[i]^.armor>0 then begin inc(k); n:=i; end;
  3369.   end;
  3370.  if (k=1) and (n>=0) then
  3371.   with robot[n]^ do
  3372.    begin inc(wins); won:=true; end;
  3373. end;
  3374.  
  3375. procedure init_bout;
  3376. var
  3377.  i,j,k:integer;
  3378. begin
  3379.  game_cycle:=0;
  3380.  for i:=0 to max_missiles do
  3381.   with missile[i] do
  3382.    begin a:=0; source:=-1; x:=0; y:=0; lx:=0; ly:=0; mult:=1; end;
  3383.  for i:=0 to num_robots do
  3384.   with robot[i]^ do
  3385.    begin
  3386.     {FIFI}
  3387.     mem_watch:=128;
  3388.     {/FIFI}
  3389.     reset_hardware(i);
  3390.     reset_software(i);
  3391.    end;
  3392.  if graphix then setscreen;
  3393.  {FIFI}
  3394.  if graphix and (step_mode>0) then init_debug_window;
  3395.  {/FIFI}
  3396.  if not graphix then
  3397.   begin
  3398.    textcolor(7);
  3399.    {writeln(#13+'Match ',played,'/',matches,', Battle in progress...');
  3400.    writeln;}
  3401.   end;
  3402. end;
  3403.  
  3404. {
  3405. procedure toggle_graphix;
  3406. begin
  3407.  graph_mode(not graphix);
  3408.  if not graphix then
  3409.   begin
  3410.    textcolor(7);
  3411.    writeln('Match ',played,'/',matches,', Battle in progress...');
  3412.    writeln;
  3413.   end
  3414.  else setscreen;
  3415. end;
  3416. }
  3417. procedure bout;
  3418. var
  3419.  i,j,k:integer;
  3420.  c:char;
  3421.  timer:longint;
  3422.  {FIFI}
  3423.  n:integer; {loop count for mem_watch}
  3424.  {/FIFI}
  3425. begin
  3426.  if quit then exit;
  3427.  
  3428.  inc(played);
  3429.  init_bout;
  3430.  bout_over:=false;
  3431.  
  3432.  {FIFI}
  3433.  if step_mode=0 then step_loop:=false else step_loop:=true; {set/clear loop flag}
  3434.  step_count:=-1; {will be set to 0 at first iteration of REPEAT ;) }
  3435.  if graphix and (step_mode>0) then for i:=0 to num_robots do draw_robot(i);
  3436.  {/FIFI}
  3437.  
  3438.  repeat
  3439.   inc(game_cycle);
  3440.   for i:=0 to num_robots do
  3441.    if robot[i]^.armor>0 then do_robot(i);
  3442.   for i:=0 to max_missiles do
  3443.    if missile[i].a>0 then do_missile(i);
  3444.   for i:=0 to num_robots do
  3445.    for k:=0 to max_mines do
  3446.     if robot[i]^.mine[k].yield>0 then do_mine(i,k);
  3447.  
  3448.   if graphix and timing then time_delay(game_delay);
  3449.  
  3450.   if keypressed then c:=upcase(readkey) else c:=#255;
  3451.   case c of
  3452.    {FIFI}
  3453.    'X': if not robot[0]^.is_locked then
  3454.          begin
  3455.           if not graphix then toggle_graphix;
  3456.           if robot[0]^.armor>0 then
  3457.            begin
  3458.             if temp_mode>0 then step_mode:=temp_mode else step_mode:=1;
  3459.             step_count:=-1;
  3460.             init_debug_window;
  3461.            end;
  3462.          end;
  3463.    {/FIFI}
  3464.    '+','=':if game_delay<100 then
  3465.             case game_delay of
  3466.               000..004:game_delay:=005;
  3467.               005..009:game_delay:=010;
  3468.               010..014:game_delay:=015;
  3469.               015..019:game_delay:=020;
  3470.               020..029:game_delay:=030;
  3471.               030..039:game_delay:=040;
  3472.               040..049:game_delay:=050;
  3473.               050..059:game_delay:=060;
  3474.               060..074:game_delay:=075;
  3475.               075..100:game_delay:=100;
  3476.             end;
  3477.    '-','_':if game_delay>0 then
  3478.             case game_delay of
  3479.               000..005:game_delay:=000;
  3480.               006..010:game_delay:=005;
  3481.               011..015:game_delay:=010;
  3482.               016..020:game_delay:=015;
  3483.               021..030:game_delay:=020;
  3484.               031..040:game_delay:=030;
  3485.               041..050:game_delay:=040;
  3486.               051..060:game_delay:=050;
  3487.               061..075:game_delay:=060;
  3488.               076..100:game_delay:=075;
  3489.             end;
  3490.    'G':toggle_graphix;
  3491.    else process_keypress(c);
  3492.   end; flushkey;
  3493.   if game_delay<0 then game_delay:=0;
  3494.   if game_delay>100 then game_delay:=100;
  3495.   case game_delay of
  3496.    000..001:k:=100;
  3497.    002..005:k:=50;
  3498.    006..010:k:=25;
  3499.    011..025:k:=20;
  3500.    026..040:k:=10;
  3501.    041..070:k:=5;
  3502.    071..maxint:k:=1;
  3503.    else k:=10;
  3504.   end;
  3505.   if not graphix then k:=100;
  3506.   if graphix then
  3507.    begin
  3508.     if ((game_cycle mod k)=0) or (game_cycle=10) then update_cycle_window;
  3509.    end else begin
  3510.     if (update_timer<>mem[0:$46C] shr 1) then update_cycle_window;
  3511.     update_timer:=mem[0:$46C] shr 1;
  3512.    end;
  3513.  until quit or gameover or bout_over;
  3514.  update_cycle_window;
  3515.  {if (not graphix) then writeln;}
  3516.  score_robots;
  3517.  show_statistics;
  3518. end;
  3519.  
  3520. procedure write_report;
  3521. var
  3522.  i,j,k:integer;
  3523.  f:text;
  3524. begin
  3525.  assign(f,main_filename+report_ext);
  3526.  rewrite(f);
  3527.  writeln(f,num_robots+1);
  3528.  for i:=0 to num_robots do
  3529.   with robot[i]^ do
  3530.    case report_type of
  3531.     2:writeln(f,wins,' ',trials,' ',kills,' ',deaths,' ',fn,' ');
  3532.     3:writeln(f,wins,' ',trials,' ',kills,' ',deaths,' ',armor,' ',
  3533.                 heat,' ',shots_fired,' ',fn,' ');
  3534.     4:writeln(f,wins,' ',trials,' ',kills,' ',deaths,' ',armor,' ',
  3535.                 heat,' ',shots_fired,' ',hits,' ',damage_total,' ',
  3536.                 cycles_lived,' ',error_count,' ',fn,' ');
  3537.     else writeln(f,wins,' ',trials,' ',fn,' ');
  3538.    end;
  3539.  close(f);
  3540. end;
  3541.  
  3542. procedure begin_window;
  3543. var
  3544.  s:string;
  3545. begin
  3546.  if (not graphix) or (not windoze) then exit;
  3547.  setscreen;
  3548.  viewport(0,0,639,479);
  3549.  box(100,150,539,200);
  3550.  hole(105,155,534,195);
  3551.  setfillpattern(gray50,1);
  3552.  bar(105,155,534,195);
  3553.  setcolor(15);
  3554.  s:='Press any key to begin!';
  3555.  outtextxy(320-((length(s) shl 3) shr 1),172,s);
  3556.  flushkey; readkey;
  3557.  setscreen;
  3558. end;
  3559.  
  3560. procedure main;
  3561. var
  3562.  i,j,k,l,n,w:integer;
  3563. begin
  3564.  if graphix then begin_window;
  3565.  if matches>0 then
  3566.   for i:=1 to matches do
  3567.    bout;
  3568.  if not graphix then writeln;
  3569.  if quit then exit;
  3570.  if matches>1 then  {--Calculate overall statistics--}
  3571.   begin
  3572.    writeln; writeln;
  3573.    graph_mode(false);
  3574.    textcolor(15);
  3575.    writeln('Bout complete! (',matches,' matches)');
  3576.    writeln;
  3577.    k:=0; w:=0;
  3578.    for i:=0 to num_robots do
  3579.     with robot[i]^ do
  3580.      begin
  3581.       if wins=w then begin inc(k); end;
  3582.       if wins>w then begin k:=1; n:=i; w:=wins; end;
  3583.      end;
  3584.    writeln('Robot           Wins  Matches  Kills  Deaths    Shots');
  3585.    writeln('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
  3586.    for i:=0 to num_robots do
  3587.     with robot[i]^ do
  3588.      begin
  3589.       textcolor(robot_color(i));
  3590.       writeln(addfront(cstr(i+1),2)+' - '+addrear(fn,8)
  3591.              +addfront(cstr(wins),7)+addfront(cstr(trials),8)
  3592.              +addfront(cstr(kills),8)+addfront(cstr(deaths),8)
  3593.              +addfront(cstr(shots_fired),9));
  3594.      end;
  3595.    textcolor(15);
  3596.    writeln;
  3597.    if k=1 then writeln('Robot #',n+1,' (',robot[n]^.fn,') wins the bout! (score: ',w,'/',matches,')')
  3598.           else writeln('There is no clear victor!');
  3599.    writeln;
  3600.   end
  3601.  else if graphix then
  3602.   begin {matches=1 also}
  3603.    graph_mode(false);
  3604.    show_statistics;
  3605.   end;
  3606.  if report then write_report;
  3607. end;
  3608.  
  3609. begin
  3610.  init;
  3611.  main;
  3612.  shutdown;
  3613. end.
  3614.